diff --git a/.gitignore b/.gitignore index 3d658a9..0b79b02 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ .npmrc npm-debug.log node_modules -.babelrc -dist +.babelrc \ No newline at end of file diff --git a/README.md b/README.md index 8939118..014fb81 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ Pure JavaScript Bitshares/Graphene library for node.js and browsers. Can be used to construct, sign and broadcast transactions in JavaScript, and to easily obtain data from the blockchain via public apis. -Most of this code was written by [jcalfeee](https://github.com/jcalfee), my work was mostly just repackaging to a discrete npm package. +Most of this code was written by [jcalfee](https://github.com/jcalfee), my work was mostly just repackaging to a discrete npm package. ## Setup diff --git a/build/peerplaysjs-lib.js b/build/peerplaysjs-lib.js new file mode 100644 index 0000000..7ed675b --- /dev/null +++ b/build/peerplaysjs-lib.js @@ -0,0 +1,24730 @@ +(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.steemJS = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i} [signer_pubkeys = null] - Optional ["GPHAbc9Def0...", ...]. These are additional signing keys. Some balance claims require propritary address formats, the witness node can't tell us which ones are needed so they must be passed in. If the witness node can figure out a signing key (mostly all other transactions), it should not be passed in here. + @arg {boolean} [broadcast = false] + */ + + }, { + key: "process_transaction", + value: function process_transaction(cwallet) { + var _this = this; + + var signer_pubkeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var broadcast = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + + var wallet_object = cwallet.wallet.wallet_object; + if (Apis.instance().chain_id !== wallet_object.get("chain_id")) return Promise.reject("Mismatched chain_id; expecting " + wallet_object.get("chain_id") + ", but got " + Apis.instance().chain_id); + + return this.set_required_fees().then(function () { + var signer_pubkeys_added = {}; + if (signer_pubkeys) { + + // Balance claims are by address, only the private + // key holder can know about these additional + // potential keys. + var pubkeys = cwallet.getPubkeys_having_PrivateKey(signer_pubkeys); + if (!pubkeys.length) throw new Error("Missing signing key"); + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = pubkeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var pubkey_string = _step.value; + + var private_key = cwallet.getPrivateKey(pubkey_string); + _this.add_signer(private_key, pubkey_string); + signer_pubkeys_added[pubkey_string] = true; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } + + return _this.get_potential_signatures().then(function (_ref) { + var pubkeys = _ref.pubkeys, + addys = _ref.addys; + + var my_pubkeys = cwallet.getPubkeys_having_PrivateKey(pubkeys, addys); + + //{//Testing only, don't send All public keys! + // var pubkeys_all = PrivateKeyStore.getPubkeys() // All public keys + // this.get_required_signatures(pubkeys_all).then( required_pubkey_strings => + // console.log('get_required_signatures all\t',required_pubkey_strings.sort(), pubkeys_all)) + // this.get_required_signatures(my_pubkeys).then( required_pubkey_strings => + // console.log('get_required_signatures normal\t',required_pubkey_strings.sort(), pubkeys)) + //} + + return _this.get_required_signatures(my_pubkeys).then(function (required_pubkeys) { + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = required_pubkeys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var _pubkey_string = _step2.value; + + if (signer_pubkeys_added[_pubkey_string]) continue; + var private_key = cwallet.getPrivateKey(_pubkey_string); + if (!private_key) + // This should not happen, get_required_signatures will only + // returned keys from my_pubkeys + throw new Error("Missing signing key for " + _pubkey_string); + _this.add_signer(private_key, _pubkey_string); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + }); + }).then(function () { + return broadcast ? _this.broadcast() : _this.serialize(); + }); + }); + } + + /** Typically this is called automatically just prior to signing. Once finalized this transaction can not be changed. */ + + }, { + key: "finalize", + value: function finalize() { + var _this2 = this; + + return new Promise(function (resolve, reject) { + + if (_this2.tr_buffer) { + throw new Error("already finalized"); + } + + resolve(Apis.instance().db_api().exec("get_objects", [["2.1.0"]]).then(function (r) { + head_block_time_string = r[0].time; + if (_this2.expiration === 0) _this2.expiration = base_expiration_sec() + ChainConfig.expire_in_secs; + _this2.ref_block_num = r[0].head_block_number & 0xFFFF; + _this2.ref_block_prefix = new Buffer(r[0].head_block_id, 'hex').readUInt32LE(4); + //DEBUG console.log("ref_block",@ref_block_num,@ref_block_prefix,r) + + var iterable = _this2.operations; + for (var i = 0, op; i < iterable.length; i++) { + op = iterable[i]; + if (op[1]["finalize"]) { + op[1].finalize(); + } + + var _type = ops.operation.st_operations[op[0]]; + var hexBuffer = _type.toBuffer(op[1]).toString("hex"); + console.log("Operation %s: %O => %s (%d bytes)", _type.operation_name, op[1], hexBuffer, hexBuffer.length / 2); + } + _this2.tr_buffer = ops.transaction.toBuffer(_this2); + })); + }); + } + + /** @return {string} hex transaction ID */ + + }, { + key: "id", + value: function id() { + if (!this.tr_buffer) { + throw new Error("not finalized"); + } + return hash.sha256(this.tr_buffer).toString('hex').substring(0, 40); + } + + /** + Typically one will use {@link this.add_type_operation} instead. + @arg {array} operation - [operation_id, operation] + */ + + }, { + key: "add_operation", + value: function add_operation(operation) { + if (this.tr_buffer) { + throw new Error("already finalized"); + } + assert(operation, "operation"); + if (!Array.isArray(operation)) { + throw new Error("Expecting array [operation_id, operation]"); + } + this.operations.push(operation); + return; + } + }, { + key: "get_type_operation", + value: function get_type_operation(name, operation) { + if (this.tr_buffer) { + throw new Error("already finalized"); + } + assert(name, "name"); + assert(operation, "operation"); + var _type = ops[name]; + assert(_type, "Unknown operation " + name); + var operation_id = ChainTypes.operations[_type.operation_name]; + if (operation_id === undefined) { + throw new Error("unknown operation: " + _type.operation_name); + } + if (!operation.fee) { + operation.fee = { amount: 0, asset_id: 0 }; + } + if (name === 'proposal_create') { + operation.expiration_time || (operation.expiration_time = base_expiration_sec() + ChainConfig.expire_in_secs_proposal); + } + var operation_instance = _type.fromObject(operation); + return [operation_id, operation_instance]; + } + + /** optional: there is a deafult expiration */ + + }, { + key: "set_expire_seconds", + value: function set_expire_seconds(sec) { + if (this.tr_buffer) { + throw new Error("already finalized"); + } + return this.expiration = base_expiration_sec() + sec; + } + + /* Wraps this transaction in a proposal_create transaction */ + + }, { + key: "propose", + value: function propose(proposal_create_options) { + if (this.tr_buffer) { + throw new Error("already finalized"); + } + if (!this.operations.length) { + throw new Error("add operation first"); + } + + assert(proposal_create_options, "proposal_create_options"); + assert(proposal_create_options.fee_paying_account, "proposal_create_options.fee_paying_account"); + + var proposed_ops = this.operations.map(function (op) { + return { op: op }; + }); + + this.operations = []; + this.signatures = []; + this.signer_private_keys = []; + proposal_create_options.proposed_ops = proposed_ops; + this.add_type_operation("proposal_create", proposal_create_options); + return this; + } + }, { + key: "has_proposed_operation", + value: function has_proposed_operation() { + var hasProposed = false; + for (var i = 0; i < this.operations.length; i++) { + if ("proposed_ops" in this.operations[i][1]) { + hasProposed = true; + break; + } + } + + return hasProposed; + } + + /** optional: the fees can be obtained from the witness node */ + + }, { + key: "set_required_fees", + value: function set_required_fees(asset_id) { + var _this3 = this; + + var fee_pool; + if (this.tr_buffer) { + throw new Error("already finalized"); + } + if (!this.operations.length) { + throw new Error("add operations first"); + } + var operations = []; + for (var i = 0, op; i < this.operations.length; i++) { + op = this.operations[i]; + operations.push(ops.operation.toObject(op)); + } + + if (!asset_id) { + var op1_fee = operations[0][1].fee; + if (op1_fee && op1_fee.asset_id !== null) { + asset_id = op1_fee.asset_id; + } else { + asset_id = "1.3.0"; + } + } + + var promises = [Apis.instance().db_api().exec("get_required_fees", [operations, asset_id])]; + + var feeAssetPromise = null; + if (asset_id !== "1.3.0") { + // This handles the fallback to paying fees in BTS if the fee pool is empty. + promises.push(Apis.instance().db_api().exec("get_required_fees", [operations, "1.3.0"])); + promises.push(Apis.instance().db_api().exec("get_objects", [[asset_id]])); + } + + return Promise.all(promises).then(function (results) { + var _results = _slicedToArray(results, 3), + fees = _results[0], + coreFees = _results[1], + asset = _results[2]; + + asset = asset ? asset[0] : null; + + var dynamicPromise = asset_id !== "1.3.0" && asset ? Apis.instance().db_api().exec("get_objects", [[asset.dynamic_asset_data_id]]) : new Promise(function (resolve, reject) { + resolve(); + }); + + return dynamicPromise.then(function (dynamicObject) { + if (asset_id !== "1.3.0") { + fee_pool = dynamicObject ? dynamicObject[0].fee_pool : 0; + var totalFees = 0; + for (var j = 0, fee; j < coreFees.length; j++) { + fee = coreFees[j]; + totalFees += fee.amount; + } + + if (totalFees > parseInt(fee_pool, 10)) { + fees = coreFees; + asset_id = "1.3.0"; + } + } + + // Proposed transactions need to be flattened + var flat_assets = []; + var flatten = function flatten(obj) { + if (Array.isArray(obj)) { + for (var k = 0, item; k < obj.length; k++) { + item = obj[k]; + flatten(item); + } + } else { + flat_assets.push(obj); + } + return; + }; + flatten(fees); + + var asset_index = 0; + + var set_fee = function set_fee(operation) { + if (!operation.fee || operation.fee.amount === 0 || operation.fee.amount.toString && operation.fee.amount.toString() === "0" // Long + ) { + operation.fee = flat_assets[asset_index]; + // console.log("new operation.fee", operation.fee) + } else { + // console.log("old operation.fee", operation.fee) + } + asset_index++; + if (operation.proposed_ops) { + var result = []; + for (var y = 0; y < operation.proposed_ops.length; y++) { + result.push(set_fee(operation.proposed_ops[y].op[1])); + }return result; + } + }; + for (var _i = 0; _i < _this3.operations.length; _i++) { + set_fee(_this3.operations[_i][1]); + } + }); + //DEBUG console.log('... get_required_fees',operations,asset_id,flat_assets) + }); + } + }, { + key: "get_potential_signatures", + value: function get_potential_signatures() { + var tr_object = ops.signed_transaction.toObject(this); + return Promise.all([Apis.instance().db_api().exec("get_potential_signatures", [tr_object]), Apis.instance().db_api().exec("get_potential_address_signatures", [tr_object])]).then(function (results) { + return { pubkeys: results[0], addys: results[1] }; + }); + } + }, { + key: "get_required_signatures", + value: function get_required_signatures(available_keys) { + if (!available_keys.length) { + return Promise.resolve([]); + } + var tr_object = ops.signed_transaction.toObject(this); + //DEBUG console.log('... tr_object',tr_object) + return Apis.instance().db_api().exec("get_required_signatures", [tr_object, available_keys]).then(function (required_public_keys) { + //DEBUG console.log('... get_required_signatures',required_public_keys) + return required_public_keys; + }); + } + }, { + key: "add_signer", + value: function add_signer(private_key) { + var public_key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : private_key.toPublicKey(); + + + assert(private_key.d, "required PrivateKey object"); + + if (this.signed) { + throw new Error("already signed"); + } + if (!public_key.Q) { + public_key = PublicKey.fromPublicKeyString(public_key); + } + // prevent duplicates + var spHex = private_key.toHex(); + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = this.signer_private_keys[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var sp = _step3.value; + + if (sp[0].toHex() === spHex) return; + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + + this.signer_private_keys.push([private_key, public_key]); + } + }, { + key: "sign", + value: function sign() { + var chain_id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Apis.instance().chain_id; + + if (!this.tr_buffer) { + throw new Error("not finalized"); + } + if (this.signed) { + throw new Error("already signed"); + } + if (!this.signer_private_keys.length) { + throw new Error("Transaction was not signed. Do you have a private key? [no_signers]"); + } + var end = this.signer_private_keys.length; + for (var i = 0; 0 < end ? i < end : i > end; 0 < end ? i++ : i++) { + var _signer_private_keys$ = _slicedToArray(this.signer_private_keys[i], 2), + private_key = _signer_private_keys$[0], + public_key = _signer_private_keys$[1]; + + var sig = Signature.signBuffer(Buffer.concat([new Buffer(chain_id, 'hex'), this.tr_buffer]), private_key, public_key); + this.signatures.push(sig.toBuffer()); + } + this.signer_private_keys = []; + this.signed = true; + return; + } + }, { + key: "serialize", + value: function serialize() { + return ops.signed_transaction.toObject(this); + } + }, { + key: "toObject", + value: function toObject() { + return ops.signed_transaction.toObject(this); + } + }, { + key: "broadcast", + value: function broadcast(was_broadcast_callback) { + var _this4 = this; + + if (this.tr_buffer) { + return this._broadcast(was_broadcast_callback); + } else { + return this.finalize().then(function () { + return _this4._broadcast(was_broadcast_callback); + }); + } + } + }]); + + return TransactionBuilder; +}(); + +var base_expiration_sec = function base_expiration_sec() { + var head_block_sec = Math.ceil(getHeadBlockDate().getTime() / 1000); + var now_sec = Math.ceil(Date.now() / 1000); + // The head block time should be updated every 3 seconds. If it isn't + // then help the transaction to expire (use head_block_sec) + if (now_sec - head_block_sec > 30) { + return head_block_sec; + } + // If the user's clock is very far behind, use the head block time. + return Math.max(now_sec, head_block_sec); +}; + +function _broadcast(was_broadcast_callback) { + var _this5 = this; + + return new Promise(function (resolve, reject) { + + if (!_this5.signed) { + _this5.sign(); + } + if (!_this5.tr_buffer) { + throw new Error("not finalized"); + } + if (!_this5.signatures.length) { + throw new Error("not signed"); + } + if (!_this5.operations.length) { + throw new Error("no operations"); + } + + var tr_object = ops.signed_transaction.toObject(_this5); + // console.log('... broadcast_transaction_with_callback !!!') + Apis.instance().network_api().exec("broadcast_transaction_with_callback", [function (res) { + return resolve(res); + }, tr_object]).then(function () { + //console.log('... broadcast success, waiting for callback') + if (was_broadcast_callback) was_broadcast_callback(); + return; + }).catch(function (error) { + // console.log may be redundant for network errors, other errors could occur + console.log(error); + var message = error.message; + if (!message) { + message = ""; + } + reject(new Error(message + "\n" + 'graphene-crypto ' + ' digest ' + hash.sha256(_this5.tr_buffer).toString('hex') + ' transaction ' + _this5.tr_buffer.toString('hex') + ' ' + JSON.stringify(tr_object))); + return; + }); + return; + }); +} + +function getHeadBlockDate() { + return timeStringToDate(head_block_time_string); +} + +function timeStringToDate(time_string) { + if (!time_string) return new Date("1970-01-01T00:00:00.000Z"); + if (!/Z$/.test(time_string)) //does not end in Z + // https://github.com/cryptonomex/graphene/issues/368 + time_string = time_string + "Z"; + return new Date(time_string); +} + +module.exports = TransactionBuilder; +}).call(this,require("buffer").Buffer) + +},{"../../ecc":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/index.js","../../serializer":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/index.js","./ChainTypes":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/chain/src/ChainTypes.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","peerplaysjs-ws":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/chain/src/state.js":[function(require,module,exports){ +"use strict"; + +function get(state) { + return function (key) { + return state[key] || ""; + }; +} + +function set(state) { + return function (key, value) { + state[key] = value; + return this; + }; +} + +module.exports = { + get: get, + set: set +}; +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/index.js":[function(require,module,exports){ +"use strict"; + +module.exports = { + Address: require("./src/address"), + Aes: require("./src/aes"), + PrivateKey: require("./src/PrivateKey"), + PublicKey: require("./src/PublicKey"), + Signature: require("./src/signature"), + brainKey: require("./src/BrainKey"), + hash: require("./src/hash"), + key: require("./src/KeyUtils") +}; +},{"./src/BrainKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/BrainKey.js","./src/KeyUtils":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/KeyUtils.js","./src/PrivateKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PrivateKey.js","./src/PublicKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PublicKey.js","./src/address":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/address.js","./src/aes":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/aes.js","./src/hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js","./src/signature":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/signature.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/BrainKey.js":[function(require,module,exports){ +'use strict'; + +module.exports = function normalize(brainKey) { + if (typeof brainKey !== 'string') { + throw new Error("string required for brainKey"); + } + brainKey = brainKey.trim(); + return brainKey.split(/[\t\n\v\f\r ]+/).join(' '); +}; +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/KeyUtils.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var key; +var PrivateKey = require('./PrivateKey'); +var PublicKey = require('./PublicKey'); +var Address = require('./address'); +var Aes = require('./aes'); + +var hash = require('./hash'); +// var dictionary = require('./dictionary_en'); +var secureRandom = require('secure-random'); + +var _require = require('peerplaysjs-ws'), + ChainConfig = _require.ChainConfig; + +// hash for .25 second + + +var HASH_POWER_MILLS = 250; + +module.exports = key = { + + /** Uses 1 second of hashing power to create a key/password checksum. An + implementation can re-call this method with the same password to re-match + the strength of the CPU (either after moving from a desktop to a mobile, + mobile to desktop, or N years from now when CPUs are presumably stronger). + A salt is used for all the normal reasons... + @return object { + aes_private: Aes, + checksum: "{hash_iteration_count},{salt},{checksum}" + } + */ + aes_checksum: function aes_checksum(password) { + if (!(typeof password === "string")) { + throw new "password string required"(); + } + var salt = secureRandom.randomBuffer(4).toString('hex'); + var iterations = 0; + var secret = salt + password; + // hash for .1 second + var start_t = Date.now(); + while (Date.now() - start_t < HASH_POWER_MILLS) { + secret = hash.sha256(secret); + iterations += 1; + } + + var checksum = hash.sha256(secret); + var checksum_string = [iterations, salt.toString('hex'), checksum.slice(0, 4).toString('hex')].join(','); + + return { aes_private: Aes.fromSeed(secret), + checksum: checksum_string + }; + }, + + + /** Provide a matching password and key_checksum. A "wrong password" + error is thrown if the password does not match. If this method takes + much more or less than 1 second to return, one should consider updating + all encyrpted fields using a new key.key_checksum. + */ + aes_private: function aes_private(password, key_checksum) { + var _key_checksum$split = key_checksum.split(','), + _key_checksum$split2 = _slicedToArray(_key_checksum$split, 3), + iterations = _key_checksum$split2[0], + salt = _key_checksum$split2[1], + checksum = _key_checksum$split2[2]; + + var secret = salt + password; + for (var i = 0; 0 < iterations ? i < iterations : i > iterations; 0 < iterations ? i++ : i++) { + secret = hash.sha256(secret); + } + var new_checksum = hash.sha256(secret); + if (!(new_checksum.slice(0, 4).toString('hex') === checksum)) { + throw new Error("wrong password"); + } + return Aes.fromSeed(secret); + }, + + + /** + A week random number generator can run out of entropy. This should ensure even the worst random number implementation will be reasonably safe. + @param1 string entropy of at least 32 bytes + */ + random32ByteBuffer: function random32ByteBuffer() { + var entropy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.browserEntropy(); + + + if (!(typeof entropy === 'string')) { + throw new Error("string required for entropy"); + } + + if (entropy.length < 32) { + throw new Error("expecting at least 32 bytes of entropy"); + } + + var start_t = Date.now(); + + while (Date.now() - start_t < HASH_POWER_MILLS) { + entropy = hash.sha256(entropy); + }var hash_array = []; + hash_array.push(entropy); + + // Hashing for 1 second may helps the computer is not low on entropy (this method may be called back-to-back). + hash_array.push(secureRandom.randomBuffer(32)); + + return hash.sha256(Buffer.concat(hash_array)); + }, + + + suggest_brain_key: function suggest_brain_key() { + var dictionary = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ","; + var entropy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.browserEntropy(); + + + var randomBuffer = this.random32ByteBuffer(entropy); + + var word_count = 16; + var dictionary_lines = dictionary.split(','); + + if (!(dictionary_lines.length === 49744)) { + throw new Error('expecting ' + 49744 + ' but got ' + dictionary_lines.length + ' dictionary words'); + } + + var brainkey = []; + var end = word_count * 2; + + for (var i = 0; i < end; i += 2) { + + // randomBuffer has 256 bits / 16 bits per word == 16 words + var num = (randomBuffer[i] << 8) + randomBuffer[i + 1]; + + // convert into a number between 0 and 1 (inclusive) + var rndMultiplier = num / Math.pow(2, 16); + var wordIndex = Math.round(dictionary_lines.length * rndMultiplier); + + brainkey.push(dictionary_lines[wordIndex]); + } + return this.normalize_brainKey(brainkey.join(' ')); + }, + + get_random_key: function get_random_key(entropy) { + return PrivateKey.fromBuffer(this.random32ByteBuffer(entropy)); + }, + get_brainPrivateKey: function get_brainPrivateKey(brainKey) { + var sequence = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + + if (sequence < 0) { + throw new Error("invalid sequence"); + } + brainKey = key.normalize_brainKey(brainKey); + return PrivateKey.fromBuffer(hash.sha256(hash.sha512(brainKey + " " + sequence))); + }, + + + // Turn invisible space like characters into a single space + normalize_brainKey: function normalize_brainKey(brainKey) { + if (!(typeof brainKey === 'string')) { + throw new Error("string required for brainKey"); + } + + brainKey = brainKey.trim(); + return brainKey.split(/[\t\n\v\f\r ]+/).join(' '); + }, + browserEntropy: function browserEntropy() { + + var entropyStr = ""; + try { + entropyStr = new Date().toString() + " " + window.screen.height + " " + window.screen.width + " " + window.screen.colorDepth + " " + " " + window.screen.availHeight + " " + window.screen.availWidth + " " + window.screen.pixelDepth + navigator.language + " " + window.location + " " + window.history.length; + + for (var i = 0, mimeType; i < navigator.mimeTypes.length; i++) { + mimeType = navigator.mimeTypes[i]; + entropyStr += mimeType.description + " " + mimeType.type + " " + mimeType.suffixes + " "; + } + console.log("INFO\tbrowserEntropy gathered"); + } catch (error) { + //nodejs:ReferenceError: window is not defined + entropyStr = hash.sha256(new Date().toString()); + } + + var b = new Buffer(entropyStr); + entropyStr += b.toString('binary') + " " + new Date().toString(); + return entropyStr; + }, + + + // @return array of 5 legacy addresses for a pubkey string parameter. + addresses: function addresses(pubkey) { + var address_prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ChainConfig.address_prefix; + + var public_key = PublicKey.fromPublicKeyString(pubkey, address_prefix); + // S L O W + var address_string = [Address.fromPublic(public_key, false, 0).toString(address_prefix), // btc_uncompressed + Address.fromPublic(public_key, true, 0).toString(address_prefix), // btc_compressed + Address.fromPublic(public_key, false, 56).toString(address_prefix), // pts_uncompressed + Address.fromPublic(public_key, true, 56).toString(address_prefix), // pts_compressed + public_key.toAddressString(address_prefix) // bts_short, most recent format + ]; + return address_string; + } +}; +}).call(this,require("buffer").Buffer) + +},{"./PrivateKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PrivateKey.js","./PublicKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PublicKey.js","./address":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/address.js","./aes":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/aes.js","./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","peerplaysjs-ws":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/index.js","secure-random":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/secure-random/lib/secure-random.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PrivateKey.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ecurve = require('ecurve'); + +var _require = require('ecurve'), + Point = _require.Point, + getCurveByName = _require.getCurveByName; + +var secp256k1 = getCurveByName('secp256k1'); +var BigInteger = require('bigi'); + +var _require2 = require('bs58'), + encode = _require2.encode, + decode = _require2.decode; + +var assert = require('assert'); +var hash = require('./hash'); +var PublicKey = require('./PublicKey'); +var deepEqual = require("deep-equal"); + +var G = secp256k1.G, + n = secp256k1.n; + +var PrivateKey = function () { + + /** + @private see static functions + @param {BigInteger} + */ + function PrivateKey(d) { + _classCallCheck(this, PrivateKey); + + this.d = d; + } + + _createClass(PrivateKey, [{ + key: 'toWif', + value: function toWif() { + var private_key = this.toBuffer(); + // checksum includes the version + private_key = Buffer.concat([new Buffer([0x80]), private_key]); + var checksum = hash.sha256(private_key); + checksum = hash.sha256(checksum); + checksum = checksum.slice(0, 4); + var private_wif = Buffer.concat([private_key, checksum]); + return encode(private_wif); + } + + /** + @return {Point} + */ + + }, { + key: 'toPublicKeyPoint', + value: function toPublicKeyPoint() { + var Q; + return Q = secp256k1.G.multiply(this.d); + } + }, { + key: 'toPublicKey', + value: function toPublicKey() { + if (this.public_key) { + return this.public_key; + } + return this.public_key = PublicKey.fromPoint(this.toPublicKeyPoint()); + } + }, { + key: 'toBuffer', + value: function toBuffer() { + return this.d.toBuffer(32); + } + + /** ECIES */ + + }, { + key: 'get_shared_secret', + value: function get_shared_secret(public_key) { + var legacy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + public_key = toPublic(public_key); + var KB = public_key.toUncompressed().toBuffer(); + var KBP = Point.fromAffine(secp256k1, BigInteger.fromBuffer(KB.slice(1, 33)), // x + BigInteger.fromBuffer(KB.slice(33, 65)) // y + ); + var r = this.toBuffer(); + var P = KBP.multiply(BigInteger.fromBuffer(r)); + var S = P.affineX.toBuffer({ size: 32 }); + /* + the input to sha512 must be exactly 32-bytes, to match the c++ implementation + of get_shared_secret. Right now S will be shorter if the most significant + byte(s) is zero. Pad it back to the full 32-bytes + */ + if (!legacy && S.length < 32) { + pad = new Buffer(32 - S.length).fill(0); + S = Buffer.concat([pad, S]); + } + + // SHA512 used in ECIES + return hash.sha512(S); + } + + // /** ECIES (does not always match the Point.fromAffine version above) */ + // get_shared_secret(public_key){ + // public_key = toPublic(public_key) + // var P = public_key.Q.multiply( this.d ); + // var S = P.affineX.toBuffer({size: 32}); + // // ECIES, adds an extra sha512 + // return hash.sha512(S); + // } + + /** @throws {Error} - overflow of the key could not be derived */ + + }, { + key: 'child', + value: function child(offset) { + offset = Buffer.concat([this.toPublicKey().toBuffer(), offset]); + offset = hash.sha256(offset); + var c = BigInteger.fromBuffer(offset); + + if (c.compareTo(n) >= 0) throw new Error("Child offset went out of bounds, try again"); + + var derived = this.d.add(c); //.mod(n) + + if (derived.signum() === 0) throw new Error("Child offset derived to an invalid key, try again"); + + return new PrivateKey(derived); + } + + /* */ + + }, { + key: 'toByteBuffer', + value: function toByteBuffer() { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + this.appendByteBuffer(b); + return b.copy(0, b.offset); + } + }, { + key: 'toHex', + value: function toHex() { + return this.toBuffer().toString('hex'); + } + + /* */ + + }], [{ + key: 'fromBuffer', + value: function fromBuffer(buf) { + if (!Buffer.isBuffer(buf)) { + throw new Error("Expecting paramter to be a Buffer type"); + } + if (32 !== buf.length) { + console.log('WARN: Expecting 32 bytes, instead got ' + buf.length + ', stack trace:', new Error().stack); + } + if (buf.length === 0) { + throw new Error("Empty buffer"); + } + return new PrivateKey(BigInteger.fromBuffer(buf)); + } + + /** @arg {string} seed - any length string. This is private, the same seed produces the same private key every time. */ + + }, { + key: 'fromSeed', + value: function fromSeed(seed) { + // generate_private_key + if (!(typeof seed === 'string')) { + throw new Error('seed must be of type string'); + } + return PrivateKey.fromBuffer(hash.sha256(seed)); + } + + /** @return {string} Wallet Import Format (still a secret, Not encrypted) */ + + }, { + key: 'fromWif', + value: function fromWif(_private_wif) { + var private_wif = new Buffer(decode(_private_wif)); + var version = private_wif.readUInt8(0); + assert.equal(0x80, version, 'Expected version ' + 0x80 + ', instead got ' + version); + // checksum includes the version + var private_key = private_wif.slice(0, -4); + var checksum = private_wif.slice(-4); + var new_checksum = hash.sha256(private_key); + new_checksum = hash.sha256(new_checksum); + new_checksum = new_checksum.slice(0, 4); + var isEqual = deepEqual(checksum, new_checksum); //, 'Invalid checksum' + if (!isEqual) { + throw new Error("Checksum did not match"); + } + private_key = private_key.slice(1); + private_key = private_key.slice(0, 32); + return PrivateKey.fromBuffer(private_key); + } + }, { + key: 'fromHex', + value: function fromHex(hex) { + return PrivateKey.fromBuffer(new Buffer(hex, 'hex')); + } + }]); + + return PrivateKey; +}(); + +module.exports = PrivateKey; + +var toPublic = function toPublic(data) { + return data == null ? data : data.Q ? data : PublicKey.fromStringOrThrow(data); +}; +}).call(this,require("buffer").Buffer) + +},{"./PublicKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PublicKey.js","./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js","bs58":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bs58/index.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","deep-equal":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/index.js","ecurve":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PublicKey.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var BigInteger = require('bigi'); + +var _require = require('ecurve'), + Point = _require.Point, + getCurveByName = _require.getCurveByName; + +var secp256k1 = getCurveByName('secp256k1'); + +var _require2 = require('bs58'), + encode = _require2.encode, + decode = _require2.decode; + +var hash = require('./hash'); + +var _require3 = require('peerplaysjs-ws'), + ChainConfig = _require3.ChainConfig; + +var assert = require('assert'); +var deepEqual = require("deep-equal"); + +var G = secp256k1.G, + n = secp256k1.n; + +var PublicKey = function () { + + /** @param {Point} public key */ + function PublicKey(Q) { + _classCallCheck(this, PublicKey); + + this.Q = Q; + } + + _createClass(PublicKey, [{ + key: 'toBuffer', + value: function toBuffer() { + var compressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.Q ? this.Q.compressed : null; + + if (this.Q === null) return new Buffer('000000000000000000000000000000000000000000000000000000000000000000', 'hex'); + return this.Q.getEncoded(compressed); + } + }, { + key: 'toUncompressed', + value: function toUncompressed() { + var buf = this.Q.getEncoded(false); + var point = Point.decodeFrom(secp256k1, buf); + return PublicKey.fromPoint(point); + } + + /** bts::blockchain::address (unique but not a full public key) */ + + }, { + key: 'toBlockchainAddress', + value: function toBlockchainAddress() { + var pub_buf = this.toBuffer(); + var pub_sha = hash.sha512(pub_buf); + return hash.ripemd160(pub_sha); + } + + /** Alias for {@link toPublicKeyString} */ + + }, { + key: 'toString', + value: function toString() { + var address_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ChainConfig.address_prefix; + + return this.toPublicKeyString(address_prefix); + } + + /** + Full public key + {return} string + */ + + }, { + key: 'toPublicKeyString', + value: function toPublicKeyString() { + var address_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ChainConfig.address_prefix; + + var pub_buf = this.toBuffer(); + var checksum = hash.ripemd160(pub_buf); + // Slice from the buffer directly, slicing from the checksum Uint8array will return the entire array each time. + var sliced = new Uint8Array(checksum.buffer.slice(0, 4)); + + // concat only accepts buffers so initialize the sliced Uint8array as a Buffer. + var addy = Buffer.concat([pub_buf, Buffer.from(sliced)]); + return address_prefix + encode(addy); + } + + /** + @arg {string} public_key - like GPHXyz... + @arg {string} address_prefix - like GPH + @return PublicKey or `null` (if the public_key string is invalid) + */ + + }, { + key: 'toAddressString', + value: function toAddressString() { + var address_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ChainConfig.address_prefix; + + var pub_buf = this.toBuffer(); + var pub_sha = hash.sha512(pub_buf); + var addy = hash.ripemd160(pub_sha); + var checksum = hash.ripemd160(addy); + addy = Buffer.concat([addy, checksum.slice(0, 4)]); + return address_prefix + encode(addy); + } + }, { + key: 'toPtsAddy', + value: function toPtsAddy() { + var pub_buf = this.toBuffer(); + var pub_sha = hash.sha256(pub_buf); + var addy = hash.ripemd160(pub_sha); + addy = Buffer.concat([new Buffer([0x38]), addy]); //version 56(decimal) + + var checksum = hash.sha256(addy); + checksum = hash.sha256(checksum); + + addy = Buffer.concat([addy, checksum.slice(0, 4)]); + return encode(addy); + } + }, { + key: 'child', + value: function child(offset) { + + assert(Buffer.isBuffer(offset), "Buffer required: offset"); + assert.equal(offset.length, 32, "offset length"); + + offset = Buffer.concat([this.toBuffer(), offset]); + offset = hash.sha256(offset); + + var c = BigInteger.fromBuffer(offset); + + if (c.compareTo(n) >= 0) throw new Error("Child offset went out of bounds, try again"); + + var cG = G.multiply(c); + var Qprime = this.Q.add(cG); + + if (secp256k1.isInfinity(Qprime)) throw new Error("Child offset derived to an invalid key, try again"); + + return PublicKey.fromPoint(Qprime); + } + + /* */ + + }, { + key: 'toByteBuffer', + value: function toByteBuffer() { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + this.appendByteBuffer(b); + return b.copy(0, b.offset); + } + }, { + key: 'toHex', + value: function toHex() { + return this.toBuffer().toString('hex'); + } + }], [{ + key: 'fromBinary', + value: function fromBinary(bin) { + return PublicKey.fromBuffer(new Buffer(bin, 'binary')); + } + }, { + key: 'fromBuffer', + value: function fromBuffer(buffer) { + if (buffer.toString('hex') === '000000000000000000000000000000000000000000000000000000000000000000') return new PublicKey(null); + return new PublicKey(Point.decodeFrom(secp256k1, buffer)); + } + }, { + key: 'fromPoint', + value: function fromPoint(point) { + return new PublicKey(point); + } + }, { + key: 'fromPublicKeyString', + value: function fromPublicKeyString(public_key) { + var address_prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ChainConfig.address_prefix; + + try { + return PublicKey.fromStringOrThrow(public_key, address_prefix); + } catch (e) { + return null; + } + } + + /** + @arg {string} public_key - like GPHXyz... + @arg {string} address_prefix - like GPH + @throws {Error} if public key is invalid + @return PublicKey + */ + + }, { + key: 'fromStringOrThrow', + value: function fromStringOrThrow(public_key) { + var address_prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ChainConfig.address_prefix; + + var prefix = public_key.slice(0, address_prefix.length); + assert.equal(address_prefix, prefix, 'Expecting key to begin with ' + address_prefix + ', instead got ' + prefix); + public_key = public_key.slice(address_prefix.length); + + public_key = new Buffer(decode(public_key), 'binary'); + var checksum = public_key.slice(-4); + public_key = public_key.slice(0, -4); + var new_checksum = hash.ripemd160(public_key); + new_checksum = new_checksum.slice(0, 4); + var isEqual = deepEqual(checksum, new_checksum); //, 'Invalid checksum' + if (!isEqual) { + throw new Error("Checksum did not match"); + } + return PublicKey.fromBuffer(public_key); + } + }, { + key: 'fromHex', + value: function fromHex(hex) { + return PublicKey.fromBuffer(new Buffer(hex, 'hex')); + } + }, { + key: 'fromPublicKeyStringHex', + value: function fromPublicKeyStringHex(hex) { + return PublicKey.fromPublicKeyString(new Buffer(hex, 'hex')); + } + + /* */ + + }]); + + return PublicKey; +}(); + +module.exports = PublicKey; +}).call(this,require("buffer").Buffer) + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js","bs58":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bs58/index.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","deep-equal":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/index.js","ecurve":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/index.js","peerplaysjs-ws":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/address.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var assert = require('assert'); + +var _require = require('peerplaysjs-ws'), + ChainConfig = _require.ChainConfig; + +var hash = require('./hash'); + +var _require2 = require('bs58'), + encode = _require2.encode, + decode = _require2.decode; + +var deepEqual = require("deep-equal"); + +/** Addresses are shortened non-reversable hashes of a public key. The full PublicKey is preferred. + @deprecated +*/ + +var Address = function () { + function Address(addy) { + _classCallCheck(this, Address); + + this.addy = addy; + } + + _createClass(Address, [{ + key: 'toBuffer', + value: function toBuffer() { + return this.addy; + } + }, { + key: 'toString', + value: function toString() { + var address_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ChainConfig.address_prefix; + + var checksum = hash.ripemd160(this.addy); + var addy = Buffer.concat([this.addy, checksum.slice(0, 4)]); + return address_prefix + encode(addy); + } + }], [{ + key: 'fromBuffer', + value: function fromBuffer(buffer) { + var _hash = hash.sha512(buffer); + var addy = hash.ripemd160(_hash); + return new Address(addy); + } + }, { + key: 'fromString', + value: function fromString(string) { + var address_prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ChainConfig.address_prefix; + + var prefix = string.slice(0, address_prefix.length); + assert.equal(address_prefix, prefix, 'Expecting key to begin with ' + address_prefix + ', instead got ' + prefix); + var addy = string.slice(address_prefix.length); + addy = new Buffer(decode(addy), 'binary'); + var checksum = addy.slice(-4); + addy = addy.slice(0, -4); + var new_checksum = hash.ripemd160(addy); + new_checksum = new_checksum.slice(0, 4); + var isEqual = deepEqual(checksum, new_checksum); //, 'Invalid checksum' + if (!isEqual) { + throw new Error("Checksum did not match"); + } + return new Address(addy); + } + }, { + key: 'fromPublic', + + + /** @return Address - Compressed PTS format (by default) */ + value: function fromPublic(public_key) { + var compressed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var version = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 56; + + var sha2 = hash.sha256(public_key.toBuffer(compressed)); + var rep = hash.ripemd160(sha2); + var versionBuffer = new Buffer(1); + versionBuffer.writeUInt8(0xFF & version, 0); + var addr = Buffer.concat([versionBuffer, rep]); + var check = hash.sha256(addr); + check = hash.sha256(check); + var buffer = Buffer.concat([addr, check.slice(0, 4)]); + return new Address(hash.ripemd160(buffer)); + } + }]); + + return Address; +}(); + +module.exports = Address; +}).call(this,require("buffer").Buffer) + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","bs58":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bs58/index.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","deep-equal":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/index.js","peerplaysjs-ws":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/aes.js":[function(require,module,exports){ +(function (Buffer){ +"use strict"; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +// https://code.google.com/p/crypto-js +var AES = require("crypto-js/aes"); +var encHex = require("crypto-js/enc-hex"); +var encBase64 = require("crypto-js/enc-base64"); +var assert = require("assert"); + +var _require = require("bytebuffer"), + Long = _require.Long; + +var hash = require('./hash'); + +/** Provides symetric encrypt and decrypt via AES. */ + +var Aes = function () { + + /** @private */ + function Aes(iv, key) { + _classCallCheck(this, Aes); + + this.iv = iv, this.key = key; + } + + /** This is an excellent way to ensure that all references to Aes can not operate anymore (example: a wallet becomes locked). An application should ensure there is only one Aes object instance for a given secret `seed`. */ + + + _createClass(Aes, [{ + key: "clear", + value: function clear() { + return this.iv = this.key = undefined; + } + + /** @arg {string} seed - secret seed may be used to encrypt or decrypt. */ + + }, { + key: "_decrypt_word_array", + + + /** @private */ + value: function _decrypt_word_array(cipher) { + // https://code.google.com/p/crypto-js/#Custom_Key_and_IV + // see wallet_records.cpp master_key::decrypt_key + return AES.decrypt({ ciphertext: cipher, salt: null }, this.key, { iv: this.iv }); + } + + /** @private */ + + }, { + key: "_encrypt_word_array", + value: function _encrypt_word_array(plaintext) { + //https://code.google.com/p/crypto-js/issues/detail?id=85 + var cipher = AES.encrypt(plaintext, this.key, { iv: this.iv }); + return encBase64.parse(cipher.toString()); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} ciphertext + @return {Buffer} binary + */ + + }, { + key: "decrypt", + value: function decrypt(ciphertext) { + if (typeof ciphertext === "string") { + ciphertext = new Buffer(ciphertext, 'binary'); + } + if (!Buffer.isBuffer(ciphertext)) { + throw new Error("buffer required"); + } + assert(ciphertext, "Missing cipher text"); + // hex is the only common format + var hex = this.decryptHex(ciphertext.toString('hex')); + return new Buffer(hex, 'hex'); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} plaintext + @return {Buffer} binary + */ + + }, { + key: "encrypt", + value: function encrypt(plaintext) { + if (typeof plaintext === "string") { + plaintext = new Buffer(plaintext, 'binary'); + } + if (!Buffer.isBuffer(plaintext)) { + throw new Error("buffer required"); + } + //assert plaintext, "Missing plain text" + // hex is the only common format + var hex = this.encryptHex(plaintext.toString('hex')); + return new Buffer(hex, 'hex'); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string|Buffer} plaintext + @return {string} hex + */ + + }, { + key: "encryptToHex", + value: function encryptToHex(plaintext) { + if (typeof plaintext === "string") { + plaintext = new Buffer(plaintext, 'binary'); + } + if (!Buffer.isBuffer(plaintext)) { + throw new Error("buffer required"); + } + //assert plaintext, "Missing plain text" + // hex is the only common format + return this.encryptHex(plaintext.toString('hex')); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} cipher - hex + @return {string} binary (could easily be readable text) + */ + + }, { + key: "decryptHex", + value: function decryptHex(cipher) { + assert(cipher, "Missing cipher text"); + // Convert data into word arrays (used by Crypto) + var cipher_array = encHex.parse(cipher); + var plainwords = this._decrypt_word_array(cipher_array); + return encHex.stringify(plainwords); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} cipher - hex + @return {Buffer} encoded as specified by the parameter + */ + + }, { + key: "decryptHexToBuffer", + value: function decryptHexToBuffer(cipher) { + assert(cipher, "Missing cipher text"); + // Convert data into word arrays (used by Crypto) + var cipher_array = encHex.parse(cipher); + var plainwords = this._decrypt_word_array(cipher_array); + var plainhex = encHex.stringify(plainwords); + return new Buffer(plainhex, 'hex'); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} cipher - hex + @arg {string} [encoding = 'binary'] - a valid Buffer encoding + @return {String} encoded as specified by the parameter + */ + + }, { + key: "decryptHexToText", + value: function decryptHexToText(cipher) { + var encoding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'binary'; + + return this.decryptHexToBuffer(cipher).toString(encoding); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} plainhex - hex format + @return {String} hex + */ + + }, { + key: "encryptHex", + value: function encryptHex(plainhex) { + var plain_array = encHex.parse(plainhex); + var cipher_array = this._encrypt_word_array(plain_array); + return encHex.stringify(cipher_array); + } + }], [{ + key: "fromSeed", + value: function fromSeed(seed) { + if (seed === undefined) { + throw new Error("seed is required"); + } + var _hash = hash.sha512(seed); + _hash = _hash.toString('hex'); + // DEBUG console.log('... fromSeed _hash',_hash) + return Aes.fromSha512(_hash); + } + }, { + key: "fromSha512", + + + /** @arg {string} hash - A 128 byte hex string, typically one would call {@link fromSeed} instead. */ + value: function fromSha512(hash) { + assert.equal(hash.length, 128, "A Sha512 in HEX should be 128 characters long, instead got " + hash.length); + var iv = encHex.parse(hash.substring(64, 96)); + var key = encHex.parse(hash.substring(0, 64)); + return new Aes(iv, key); + } + }, { + key: "fromBuffer", + value: function fromBuffer(buf) { + assert(Buffer.isBuffer(buf), "Expecting Buffer"); + assert.equal(buf.length, 64, "A Sha512 Buffer should be 64 characters long, instead got " + buf.length); + return Aes.fromSha512(buf.toString("hex")); + } + /** + @throws {Error} - "Invalid Key, ..." + @arg {PrivateKey} private_key - required and used for decryption + @arg {PublicKey} public_key - required and used to calcualte the shared secret + @arg {string} [nonce = ""] optional but should always be provided and be unique when re-using the same private/public keys more than once. This nonce is not a secret. + @arg {string|Buffer} message - Encrypted message containing a checksum + @return {Buffer} + */ + + }, { + key: "decrypt_with_checksum", + value: function decrypt_with_checksum(private_key, public_key, nonce, message) { + var legacy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + + + // Warning: Do not put `nonce = ""` in the arguments, in es6 this will not convert "null" into an emtpy string + if (nonce == null) // null or undefined + nonce = ""; + + if (!Buffer.isBuffer(message)) { + message = new Buffer(message, 'hex'); + } + + var S = private_key.get_shared_secret(public_key, legacy); + // D E B U G + // console.log('decrypt_with_checksum', { + // priv_to_pub: private_key.toPublicKey().toString(), + // pub: public_key.toPublicKeyString(), + // nonce: nonce, + // message: message.length, + // S: S.toString('hex') + // }) + + var aes = Aes.fromSeed(Buffer.concat([ + // A null or empty string nonce will not effect the hash + new Buffer("" + nonce), new Buffer(S.toString('hex'))])); + + var planebuffer = aes.decrypt(message); + if (!(planebuffer.length >= 4)) { + throw new Error("Invalid key, could not decrypt message(1)"); + } + + // DEBUG console.log('... planebuffer',planebuffer) + var checksum = planebuffer.slice(0, 4); + var plaintext = planebuffer.slice(4); + + // console.log('... checksum',checksum.toString('hex')) + // console.log('... plaintext',plaintext.toString()) + + var new_checksum = hash.sha256(plaintext); + new_checksum = new_checksum.slice(0, 4); + new_checksum = new_checksum.toString('hex'); + + if (!(checksum.toString('hex') === new_checksum)) { + throw new Error("Invalid key, could not decrypt message(2)"); + } + + return plaintext; + } + }, { + key: "encrypt_with_checksum", + + + /** Identical to {@link decrypt_with_checksum} but used to encrypt. Should not throw an error. + @return {Buffer} message - Encrypted message which includes a checksum + */ + value: function encrypt_with_checksum(private_key, public_key, nonce, message) { + + // Warning: Do not put `nonce = ""` in the arguments, in es6 this will not convert "null" into an emtpy string + + if (nonce == null) // null or undefined + nonce = ""; + + if (!Buffer.isBuffer(message)) { + message = new Buffer(message, 'binary'); + } + + var S = private_key.get_shared_secret(public_key); + + // D E B U G + // console.log('encrypt_with_checksum', { + // priv_to_pub: private_key.toPublicKey().toString() + // pub: public_key.toPublicKeyString() + // nonce: nonce + // message: message.length + // S: S.toString('hex') + // }) + + var aes = Aes.fromSeed(Buffer.concat([ + // A null or empty string nonce will not effect the hash + new Buffer("" + nonce), new Buffer(S.toString('hex'))])); + // DEBUG console.log('... S',S.toString('hex')) + var checksum = hash.sha256(message).slice(0, 4); + var payload = Buffer.concat([checksum, message]); + // DEBUG console.log('... payload',payload.toString()) + return aes.encrypt(payload); + } + }]); + + return Aes; +}(); + +module.exports = Aes; +}).call(this,require("buffer").Buffer) + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","bytebuffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bytebuffer/dist/bytebuffer.js","crypto-js/aes":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/aes.js","crypto-js/enc-base64":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/enc-base64.js","crypto-js/enc-hex":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/enc-hex.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/ecdsa.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var assert = require('assert'); // from github.com/bitcoinjs/bitcoinjs-lib from github.com/cryptocoinjs/ecdsa +var crypto = require('./hash'); +var enforceType = require('./enforce_types'); + +var BigInteger = require('bigi'); +var ECSignature = require('./ecsignature'); + +// https://tools.ietf.org/html/rfc6979#section-3.2 +function deterministicGenerateK(curve, hash, d, checkSig, nonce) { + + enforceType('Buffer', hash); + enforceType(BigInteger, d); + + if (nonce) { + hash = crypto.sha256(Buffer.concat([hash, new Buffer(nonce)])); + } + + // sanity check + assert.equal(hash.length, 32, 'Hash must be 256 bit'); + + var x = d.toBuffer(32); + var k = new Buffer(32); + var v = new Buffer(32); + + // Step B + v.fill(1); + + // Step C + k.fill(0); + + // Step D + k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0]), x, hash]), k); + + // Step E + v = crypto.HmacSHA256(v, k); + + // Step F + k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([1]), x, hash]), k); + + // Step G + v = crypto.HmacSHA256(v, k); + + // Step H1/H2a, ignored as tlen === qlen (256 bit) + // Step H2b + v = crypto.HmacSHA256(v, k); + + var T = BigInteger.fromBuffer(v); + + // Step H3, repeat until T is within the interval [1, n - 1] + while (T.signum() <= 0 || T.compareTo(curve.n) >= 0 || !checkSig(T)) { + k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0])]), k); + v = crypto.HmacSHA256(v, k); + + // Step H1/H2a, again, ignored as tlen === qlen (256 bit) + // Step H2b again + v = crypto.HmacSHA256(v, k); + + T = BigInteger.fromBuffer(v); + } + + return T; +} + +function sign(curve, hash, d, nonce) { + + var e = BigInteger.fromBuffer(hash); + var n = curve.n; + var G = curve.G; + + var r, s; + var k = deterministicGenerateK(curve, hash, d, function (k) { + // find canonically valid signature + var Q = G.multiply(k); + + if (curve.isInfinity(Q)) return false; + + r = Q.affineX.mod(n); + if (r.signum() === 0) return false; + + s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n); + if (s.signum() === 0) return false; + + return true; + }, nonce); + + var N_OVER_TWO = n.shiftRight(1); + + // enforce low S values, see bip62: 'low s values in signatures' + if (s.compareTo(N_OVER_TWO) > 0) { + s = n.subtract(s); + } + + return new ECSignature(r, s); +} + +function verifyRaw(curve, e, signature, Q) { + var n = curve.n; + var G = curve.G; + + var r = signature.r; + var s = signature.s; + + // 1.4.1 Enforce r and s are both integers in the interval [1, n − 1] + if (r.signum() <= 0 || r.compareTo(n) >= 0) return false; + if (s.signum() <= 0 || s.compareTo(n) >= 0) return false; + + // c = s^-1 mod n + var c = s.modInverse(n); + + // 1.4.4 Compute u1 = es^−1 mod n + // u2 = rs^−1 mod n + var u1 = e.multiply(c).mod(n); + var u2 = r.multiply(c).mod(n); + + // 1.4.5 Compute R = (xR, yR) = u1G + u2Q + var R = G.multiplyTwo(u1, Q, u2); + + // 1.4.5 (cont.) Enforce R is not at infinity + if (curve.isInfinity(R)) return false; + + // 1.4.6 Convert the field element R.x to an integer + var xR = R.affineX; + + // 1.4.7 Set v = xR mod n + var v = xR.mod(n); + + // 1.4.8 If v = r, output "valid", and if v != r, output "invalid" + return v.equals(r); +} + +function verify(curve, hash, signature, Q) { + // 1.4.2 H = Hash(M), already done by the user + // 1.4.3 e = H + var e = BigInteger.fromBuffer(hash); + return verifyRaw(curve, e, signature, Q); +} + +/** + * Recover a public key from a signature. + * + * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public + * Key Recovery Operation". + * + * http://www.secg.org/download/aid-780/sec1-v2.pdf + */ +function recoverPubKey(curve, e, signature, i) { + assert.strictEqual(i & 3, i, 'Recovery param is more than two bits'); + + var n = curve.n; + var G = curve.G; + + var r = signature.r; + var s = signature.s; + + assert(r.signum() > 0 && r.compareTo(n) < 0, 'Invalid r value'); + assert(s.signum() > 0 && s.compareTo(n) < 0, 'Invalid s value'); + + // A set LSB signifies that the y-coordinate is odd + var isYOdd = i & 1; + + // The more significant bit specifies whether we should use the + // first or second candidate key. + var isSecondKey = i >> 1; + + // 1.1 Let x = r + jn + var x = isSecondKey ? r.add(n) : r; + var R = curve.pointFromX(isYOdd, x); + + // 1.4 Check that nR is at infinity + var nR = R.multiply(n); + assert(curve.isInfinity(nR), 'nR is not a valid curve point'); + + // Compute -e from e + var eNeg = e.negate().mod(n); + + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + var rInv = r.modInverse(n); + + var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv); + curve.validate(Q); + + return Q; +} + +/** + * Calculate pubkey extraction parameter. + * + * When extracting a pubkey from a signature, we have to + * distinguish four different cases. Rather than putting this + * burden on the verifier, Bitcoin includes a 2-bit value with the + * signature. + * + * This function simply tries all four cases and returns the value + * that resulted in a successful pubkey recovery. + */ +function calcPubKeyRecoveryParam(curve, e, signature, Q) { + for (var i = 0; i < 4; i++) { + var Qprime = recoverPubKey(curve, e, signature, i); + + // 1.6.2 Verify Q + if (Qprime.equals(Q)) { + return i; + } + } + + throw new Error('Unable to find valid recovery factor'); +} + +module.exports = { + calcPubKeyRecoveryParam: calcPubKeyRecoveryParam, + deterministicGenerateK: deterministicGenerateK, + recoverPubKey: recoverPubKey, + sign: sign, + verify: verify, + verifyRaw: verifyRaw +}; +}).call(this,require("buffer").Buffer) + +},{"./ecsignature":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/ecsignature.js","./enforce_types":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/enforce_types.js","./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/ecsignature.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var assert = require('assert'); // from https://github.com/bitcoinjs/bitcoinjs-lib +var enforceType = require('./enforce_types'); + +var BigInteger = require('bigi'); + +function ECSignature(r, s) { + enforceType(BigInteger, r); + enforceType(BigInteger, s); + + this.r = r; + this.s = s; +} + +// Import operations +ECSignature.parseCompact = function (buffer) { + assert.equal(buffer.length, 65, 'Invalid signature length'); + var i = buffer.readUInt8(0) - 27; + + // At most 3 bits + assert.equal(i, i & 7, 'Invalid signature parameter'); + var compressed = !!(i & 4); + + // Recovery param only + i = i & 3; + + var r = BigInteger.fromBuffer(buffer.slice(1, 33)); + var s = BigInteger.fromBuffer(buffer.slice(33)); + + return { + compressed: compressed, + i: i, + signature: new ECSignature(r, s) + }; +}; + +ECSignature.fromDER = function (buffer) { + assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence'); + assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length'); + assert.equal(buffer.readUInt8(2), 0x02, 'Expected a DER integer'); + + var rLen = buffer.readUInt8(3); + assert(rLen > 0, 'R length is zero'); + + var offset = 4 + rLen; + assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)'); + + var sLen = buffer.readUInt8(offset + 1); + assert(sLen > 0, 'S length is zero'); + + var rB = buffer.slice(4, offset); + var sB = buffer.slice(offset + 2); + offset += 2 + sLen; + + if (rLen > 1 && rB.readUInt8(0) === 0x00) { + assert(rB.readUInt8(1) & 0x80, 'R value excessively padded'); + } + + if (sLen > 1 && sB.readUInt8(0) === 0x00) { + assert(sB.readUInt8(1) & 0x80, 'S value excessively padded'); + } + + assert.equal(offset, buffer.length, 'Invalid DER encoding'); + var r = BigInteger.fromDERInteger(rB); + var s = BigInteger.fromDERInteger(sB); + + assert(r.signum() >= 0, 'R value is negative'); + assert(s.signum() >= 0, 'S value is negative'); + + return new ECSignature(r, s); +}; + +// FIXME: 0x00, 0x04, 0x80 are SIGHASH_* boundary constants, importing Transaction causes a circular dependency +ECSignature.parseScriptSignature = function (buffer) { + var hashType = buffer.readUInt8(buffer.length - 1); + var hashTypeMod = hashType & ~0x80; + + assert(hashTypeMod > 0x00 && hashTypeMod < 0x04, 'Invalid hashType'); + + return { + signature: ECSignature.fromDER(buffer.slice(0, -1)), + hashType: hashType + }; +}; + +// Export operations +ECSignature.prototype.toCompact = function (i, compressed) { + if (compressed) i += 4; + i += 27; + + var buffer = new Buffer(65); + buffer.writeUInt8(i, 0); + + this.r.toBuffer(32).copy(buffer, 1); + this.s.toBuffer(32).copy(buffer, 33); + + return buffer; +}; + +ECSignature.prototype.toDER = function () { + var rBa = this.r.toDERInteger(); + var sBa = this.s.toDERInteger(); + + var sequence = []; + + // INTEGER + sequence.push(0x02, rBa.length); + sequence = sequence.concat(rBa); + + // INTEGER + sequence.push(0x02, sBa.length); + sequence = sequence.concat(sBa); + + // SEQUENCE + sequence.unshift(0x30, sequence.length); + + return new Buffer(sequence); +}; + +ECSignature.prototype.toScriptSignature = function (hashType) { + var hashTypeBuffer = new Buffer(1); + hashTypeBuffer.writeUInt8(hashType, 0); + + return Buffer.concat([this.toDER(), hashTypeBuffer]); +}; + +module.exports = ECSignature; +}).call(this,require("buffer").Buffer) + +},{"./enforce_types":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/enforce_types.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/enforce_types.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +module.exports = function enforce(type, value) { + // Copied from https://github.com/bitcoinjs/bitcoinjs-lib + switch (type) { + case 'Array': + { + if (Array.isArray(value)) return; + break; + } + + case 'Boolean': + { + if (typeof value === 'boolean') return; + break; + } + + case 'Buffer': + { + if (Buffer.isBuffer(value)) return; + break; + } + + case 'Number': + { + if (typeof value === 'number') return; + break; + } + + case 'String': + { + if (typeof value === 'string') return; + break; + } + + default: + { + if (getName(value.constructor) === getName(type)) return; + } + } + + throw new TypeError('Expected ' + (getName(type) || type) + ', got ' + value); +}; + +function getName(fn) { + // Why not fn.name: https://kangax.github.io/compat-table/es6/#function_name_property + var match = fn.toString().match(/function (.*?)\(/); + return match ? match[1] : null; +} +}).call(this,{"isBuffer":require("../../../node_modules/is-buffer/index.js")}) + +},{"../../../node_modules/is-buffer/index.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/is-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js":[function(require,module,exports){ +"use strict"; + +var createHash = require("create-hash"); +var createHmac = require("create-hmac"); + +/** @arg {string|Buffer} data + @arg {string} [digest = null] - 'hex', 'binary' or 'base64' + @return {string|Buffer} - Buffer when digest is null, or string +*/ +function sha1(data, encoding) { + return createHash('sha1').update(data).digest(encoding); +} + +/** @arg {string|Buffer} data + @arg {string} [digest = null] - 'hex', 'binary' or 'base64' + @return {string|Buffer} - Buffer when digest is null, or string +*/ +function sha256(data, encoding) { + return createHash('sha256').update(data).digest(encoding); +} + +/** @arg {string|Buffer} data + @arg {string} [digest = null] - 'hex', 'binary' or 'base64' + @return {string|Buffer} - Buffer when digest is null, or string +*/ +function sha512(data, encoding) { + return createHash('sha512').update(data).digest(encoding); +} + +function HmacSHA256(buffer, secret) { + return createHmac('sha256', secret).update(buffer).digest(); +} + +function ripemd160(data) { + return createHash('rmd160').update(data).digest(); +} + +// function hash160(buffer) { +// return ripemd160(sha256(buffer)) +// } +// +// function hash256(buffer) { +// return sha256(sha256(buffer)) +// } + +// +// function HmacSHA512(buffer, secret) { +// return crypto.createHmac('sha512', secret).update(buffer).digest() +// } + +module.exports = { + sha1: sha1, + sha256: sha256, + sha512: sha512, + HmacSHA256: HmacSHA256, + ripemd160: ripemd160 + // hash160: hash160, + // hash256: hash256, + // HmacSHA512: HmacSHA512 +}; +},{"create-hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/create-hash/browser.js","create-hmac":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/create-hmac/browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/signature.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ecdsa = require('./ecdsa'); +var hash = require('./hash'); + +var _require = require('ecurve'), + getCurveByName = _require.getCurveByName; + +var secp256k1 = getCurveByName('secp256k1'); +var assert = require('assert'); +var BigInteger = require('bigi'); +var PublicKey = require('./PublicKey'); + +var Signature = function () { + function Signature(r1, s1, i1) { + _classCallCheck(this, Signature); + + this.r = r1; + this.s = s1; + this.i = i1; + assert.equal(this.r != null, true, 'Missing parameter'); + assert.equal(this.s != null, true, 'Missing parameter'); + assert.equal(this.i != null, true, 'Missing parameter'); + } + + _createClass(Signature, [{ + key: 'toBuffer', + value: function toBuffer() { + var buf; + buf = new Buffer(65); + buf.writeUInt8(this.i, 0); + this.r.toBuffer(32).copy(buf, 1); + this.s.toBuffer(32).copy(buf, 33); + return buf; + } + }, { + key: 'recoverPublicKeyFromBuffer', + value: function recoverPublicKeyFromBuffer(buffer) { + return this.recoverPublicKey(hash.sha256(buffer)); + } + }, { + key: 'recoverPublicKey', + + + /** + @return {PublicKey} + */ + value: function recoverPublicKey(sha256_buffer) { + var Q = void 0, + e = void 0, + i = void 0; + e = BigInteger.fromBuffer(sha256_buffer); + i = this.i; + i -= 27; + i = i & 3; + Q = ecdsa.recoverPubKey(secp256k1, e, this, i); + return PublicKey.fromPoint(Q); + } + }, { + key: 'verifyBuffer', + + + /** + @param {Buffer} un-hashed + @param {./PublicKey} + @return {boolean} + */ + value: function verifyBuffer(buf, public_key) { + var _hash = hash.sha256(buf); + return this.verifyHash(_hash, public_key); + } + }, { + key: 'verifyHash', + value: function verifyHash(hash, public_key) { + assert.equal(hash.length, 32, "A SHA 256 should be 32 bytes long, instead got " + hash.length); + return ecdsa.verify(secp256k1, hash, { + r: this.r, + s: this.s + }, public_key.Q); + } + }, { + key: 'toByteBuffer', + + + /* */ + + value: function toByteBuffer() { + var b; + b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + this.appendByteBuffer(b); + return b.copy(0, b.offset); + } + }, { + key: 'toHex', + value: function toHex() { + return this.toBuffer().toString("hex"); + } + }, { + key: 'verifyHex', + value: function verifyHex(hex, public_key) { + var buf; + buf = new Buffer(hex, 'hex'); + return this.verifyBuffer(buf, public_key); + } + }], [{ + key: 'fromBuffer', + value: function fromBuffer(buf) { + var i, r, s; + assert.equal(buf.length, 65, 'Invalid signature length'); + i = buf.readUInt8(0); + assert.equal(i - 27, i - 27 & 7, 'Invalid signature parameter'); + r = BigInteger.fromBuffer(buf.slice(1, 33)); + s = BigInteger.fromBuffer(buf.slice(33)); + return new Signature(r, s, i); + } + }, { + key: 'signBuffer', + + + /** + @param {Buffer} buf + @param {PrivateKey} private_key + @return {Signature} + */ + value: function signBuffer(buf, private_key) { + var _hash = hash.sha256(buf); + return Signature.signBufferSha256(_hash, private_key); + } + + /** Sign a buffer of exactally 32 bytes in size (sha256(text)) + @param {Buffer} buf - 32 bytes binary + @param {PrivateKey} private_key + @return {Signature} + */ + + }, { + key: 'signBufferSha256', + value: function signBufferSha256(buf_sha256, private_key) { + if (buf_sha256.length !== 32 || !Buffer.isBuffer(buf_sha256)) throw new Error("buf_sha256: 32 byte buffer requred"); + var der, e, ecsignature, i, lenR, lenS, nonce; + i = null; + nonce = 0; + e = BigInteger.fromBuffer(buf_sha256); + while (true) { + ecsignature = ecdsa.sign(secp256k1, buf_sha256, private_key.d, nonce++); + der = ecsignature.toDER(); + lenR = der[3]; + lenS = der[5 + lenR]; + if (lenR === 32 && lenS === 32) { + i = ecdsa.calcPubKeyRecoveryParam(secp256k1, e, ecsignature, private_key.toPublicKey().Q); + i += 4; // compressed + i += 27; // compact // 24 or 27 :( forcing odd-y 2nd key candidate) + break; + } + if (nonce % 10 === 0) { + console.log("WARN: " + nonce + " attempts to find canonical signature"); + } + } + return new Signature(ecsignature.r, ecsignature.s, i); + } + }, { + key: 'sign', + value: function sign(string, private_key) { + return Signature.signBuffer(new Buffer(string), private_key); + } + }, { + key: 'fromHex', + value: function fromHex(hex) { + return Signature.fromBuffer(new Buffer(hex, "hex")); + } + }, { + key: 'signHex', + value: function signHex(hex, private_key) { + var buf; + buf = new Buffer(hex, 'hex'); + return Signature.signBuffer(buf, private_key); + } + }]); + + return Signature; +}(); + +module.exports = Signature; +}).call(this,require("buffer").Buffer) + +},{"./PublicKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PublicKey.js","./ecdsa":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/ecdsa.js","./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/hash.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","ecurve":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/index.js":[function(require,module,exports){ +'use strict'; + +module.exports = { + + // Primary class for creating operations + Serializer: require('./src/serializer'), + + // helper functions for creating operations + fp: require('./src/FastParser'), + + // Low level types + types: require('./src/types'), + + // Higher level operations (made out of generic types) + ops: require('./src/operations'), + + // Utility that generates JSON examples + template: require('./src/template'), + + // Serializer validation + SerializerValidation: require('./src/SerializerValidation') +}; +},{"./src/FastParser":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/FastParser.js","./src/SerializerValidation":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/SerializerValidation.js","./src/operations":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/operations.js","./src/serializer":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/serializer.js","./src/template":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/template.js","./src/types":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/types.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/FastParser.js":[function(require,module,exports){ +(function (Buffer){ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var PublicKey = require("../../ecc/src/PublicKey"); + +var FastParser = function () { + function FastParser() { + _classCallCheck(this, FastParser); + } + + _createClass(FastParser, null, [{ + key: 'fixed_data', + value: function fixed_data(b, len, buffer) { + if (!b) { + return; + } + if (buffer) { + var data = buffer.slice(0, len).toString('binary'); + b.append(data, 'binary'); + while (len-- > data.length) { + b.writeUint8(0); + } + } else { + var b_copy = b.copy(b.offset, b.offset + len); + b.skip(len); + return new Buffer(b_copy.toBinary(), 'binary'); + } + } + }, { + key: 'public_key', + value: function public_key(b, _public_key) { + if (!b) { + return; + } + if (_public_key) { + var buffer = _public_key.toBuffer(); + b.append(buffer.toString('binary'), 'binary'); + return; + } else { + buffer = FastParser.fixed_data(b, 33); + return PublicKey.fromBuffer(buffer); + } + } + }, { + key: 'ripemd160', + value: function ripemd160(b, _ripemd) { + if (!b) { + return; + } + if (_ripemd) { + FastParser.fixed_data(b, 20, _ripemd); + return; + } else { + return FastParser.fixed_data(b, 20); + } + } + }, { + key: 'sha256', + value: function sha256(b, _sha) { + if (!b) { + return; + } + if (_sha) { + FastParser.fixed_data(b, 32, _sha); + return; + } else { + return FastParser.fixed_data(b, 32); + } + } + }, { + key: 'time_point_sec', + value: function time_point_sec(b, epoch) { + if (epoch) { + epoch = Math.ceil(epoch / 1000); + b.writeInt32(epoch); + return; + } else { + epoch = b.readInt32(); // fc::time_point_sec + return new Date(epoch * 1000); + } + } + }]); + + return FastParser; +}(); + +module.exports = FastParser; +}).call(this,require("buffer").Buffer) + +},{"../../ecc/src/PublicKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PublicKey.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/SerializerValidation.js":[function(require,module,exports){ +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _require = require('bytebuffer'), + Long = _require.Long; + +var ChainTypes = require('../../chain/src/ChainTypes'); + +var MAX_SAFE_INT = 9007199254740991; +var MIN_SAFE_INT = -9007199254740991; + +/** + Most validations are skipped and the value returned unchanged when an empty string, null, or undefined is encountered (except "required"). + + Validations support a string format for dealing with large numbers. +*/ +var _my = { + + is_empty: function is_empty(value) { + return value === null || value === undefined; + }, + + required: function required(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + throw new Error('value required ' + field_name + ' ' + value); + } + return value; + }, + require_long: function require_long(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (!Long.isLong(value)) { + throw new Error('Long value required ' + field_name + ' ' + value); + } + return value; + }, + string: function string(value) { + if (this.is_empty(value)) { + return value; + } + if (typeof value !== "string") { + throw new Error('string required: ' + value); + } + return value; + }, + number: function number(value) { + if (this.is_empty(value)) { + return value; + } + if (typeof value !== "number") { + throw new Error('number required: ' + value); + } + return value; + }, + whole_number: function whole_number(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (/\./.test(value)) { + throw new Error('whole number required ' + field_name + ' ' + value); + } + return value; + }, + unsigned: function unsigned(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (/-/.test(value)) { + throw new Error('unsigned required ' + field_name + ' ' + value); + } + return value; + }, + + + is_digits: function is_digits(value) { + if (typeof value === "numeric") { + return true; + } + return (/^[0-9]+$/.test(value) + ); + }, + + to_number: function to_number(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + this.no_overflow53(value, field_name); + var int_value = function () { + if (typeof value === "number") { + return value; + } else { + return parseInt(value); + } + }(); + return int_value; + }, + + to_long: function to_long(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (Long.isLong(value)) { + return value; + } + + this.no_overflow64(value, field_name); + if (typeof value === "number") { + value = "" + value; + } + return Long.fromString(value); + }, + to_ulong: function to_ulong(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (Long.isLong(value)) { + return value; + } + + this.no_overflow64(value, field_name, true); + if (typeof value === "number") { + value = "" + value; + } + return Long.fromString(value, true); + }, + to_string: function to_string(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (typeof value === "string") { + return value; + } + if (typeof value === "number") { + this.no_overflow53(value, field_name); + return "" + value; + } + if (Long.isLong(value)) { + return value.toString(); + } + throw 'unsupported type ' + field_name + ': (' + (typeof value === 'undefined' ? 'undefined' : _typeof(value)) + ') ' + value; + }, + require_test: function require_test(regex, value) { + var field_name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; + + if (this.is_empty(value)) { + return value; + } + if (!regex.test(value)) { + throw new Error('unmatched ' + regex + ' ' + field_name + ' ' + value); + } + return value; + }, + + + require_match: function require_match(regex, value) { + var field_name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; + + if (this.is_empty(value)) { + return value; + } + var match = value.match(regex); + if (match === null) { + throw new Error('unmatched ' + regex + ' ' + field_name + ' ' + value); + } + return match; + }, + + require_object_id: function require_object_id(value, field_name) { + return require_match(/^([0-9]+)\.([0-9]+)\.([0-9]+)$/, value, field_name); + }, + + // Does not support over 53 bits + require_range: function require_range(min, max, value) { + var field_name = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ""; + + if (this.is_empty(value)) { + return value; + } + var number = this.to_number(value); + if (value < min || value > max) { + throw new Error('out of range ' + value + ' ' + field_name + ' ' + value); + } + return value; + }, + + + require_object_type: function require_object_type() { + var reserved_spaces = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; + var type = arguments[1]; + var value = arguments[2]; + var field_name = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ""; + + if (this.is_empty(value)) { + return value; + } + var object_type = ChainTypes.object_type[type]; + if (!object_type) { + throw new Error('Unknown object type ' + type + ' ' + field_name + ' ' + value); + } + var re = new RegExp(reserved_spaces + '.' + object_type + '.[0-9]+$'); + if (!re.test(value)) { + throw new Error('Expecting ' + type + ' in format ' + (reserved_spaces + '.' + object_type + '.[0-9]+ ') + ('instead of ' + value + ' ' + field_name + ' ' + value)); + } + return value; + }, + + get_instance: function get_instance(reserve_spaces, type, value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_type(reserve_spaces, type, value, field_name); + return this.to_number(value.split('.')[2]); + }, + + require_relative_type: function require_relative_type(type, value, field_name) { + this.require_object_type(0, type, value, field_name); + return value; + }, + + get_relative_instance: function get_relative_instance(type, value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_type(0, type, value, field_name); + return this.to_number(value.split('.')[2]); + }, + + require_protocol_type: function require_protocol_type(type, value, field_name) { + this.require_object_type(1, type, value, field_name); + return value; + }, + + get_protocol_instance: function get_protocol_instance(type, value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_type(1, type, value, field_name); + return this.to_number(value.split('.')[2]); + }, + + get_protocol_type: function get_protocol_type(value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_id(value, field_name); + var values = value.split('.'); + return this.to_number(values[1]); + }, + + get_protocol_type_name: function get_protocol_type_name(value, field_name) { + if (this.is_empty(value)) { + return value; + } + var type_id = this.get_protocol_type(value, field_name); + return Object.keys(ChainTypes.object_type)[type_id]; + }, + + + require_implementation_type: function require_implementation_type(type, value, field_name) { + this.require_object_type(2, type, value, field_name); + return value; + }, + + get_implementation_instance: function get_implementation_instance(type, value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_type(2, type, value, field_name); + return this.to_number(value.split('.')[2]); + }, + + // signed / unsigned decimal + no_overflow53: function no_overflow53(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (typeof value === "number") { + if (value > MAX_SAFE_INT || value < MIN_SAFE_INT) { + throw new Error('overflow ' + field_name + ' ' + value); + } + return; + } + if (typeof value === "string") { + var int = parseInt(value); + if (value > MAX_SAFE_INT || value < MIN_SAFE_INT) { + throw new Error('overflow ' + field_name + ' ' + value); + } + return; + } + if (Long.isLong(value)) { + // typeof value.toInt() is 'number' + this.no_overflow53(value.toInt(), field_name); + return; + } + throw 'unsupported type ' + field_name + ': (' + (typeof value === 'undefined' ? 'undefined' : _typeof(value)) + ') ' + value; + }, + + + // signed / unsigned whole numbers only + no_overflow64: function no_overflow64(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + var unsigned = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // https://github.com/dcodeIO/Long.js/issues/20 + if (Long.isLong(value)) { + return; + } + + // BigInteger#isBigInteger https://github.com/cryptocoinjs/bigi/issues/20 + if (value.t !== undefined && value.s !== undefined) { + this.no_overflow64(value.toString(), field_name, unsigned); + + return; + } + + if (typeof value === "string") { + // remove leading zeros, will cause a false positive + value = value.replace(/^0+/, ''); + // remove trailing zeros + while (/0$/.test(value)) { + value = value.substring(0, value.length - 1); + } + if (/\.$/.test(value)) { + // remove trailing dot + value = value.substring(0, value.length - 1); + } + if (value === "") { + value = "0"; + } + + var long_string = Long.fromString(value, unsigned).toString(); + + if (long_string !== value.trim()) { + throw new Error('overflow ' + field_name + ' ' + value); + } + return; + } + if (typeof value === "number") { + if (value > MAX_SAFE_INT || value < MIN_SAFE_INT) { + throw new Error('overflow ' + field_name + ' ' + value); + } + return; + } + + throw 'unsupported type ' + field_name + ': (' + (typeof value === 'undefined' ? 'undefined' : _typeof(value)) + ') ' + value; + } +}; + +module.exports = _my; +},{"../../chain/src/ChainTypes":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/chain/src/ChainTypes.js","bytebuffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bytebuffer/dist/bytebuffer.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/error_with_cause.js":[function(require,module,exports){ +"use strict"; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** Exception nesting. */ +var ErrorWithCause = function () { + function ErrorWithCause(message, cause) { + _classCallCheck(this, ErrorWithCause); + + this.message = message; + if (typeof cause !== "undefined" && cause !== null ? cause.message : undefined) { + this.message = "cause\t" + cause.message + "\t" + this.message; + } + + var stack = ""; //(new Error).stack + if (typeof cause !== "undefined" && cause !== null ? cause.stack : undefined) { + stack = "caused by\n\t" + cause.stack + "\t" + stack; + } + + this.stack = this.message + "\n" + stack; + } + + _createClass(ErrorWithCause, null, [{ + key: "throw", + value: function _throw(message, cause) { + var msg = message; + if (typeof cause !== "undefined" && cause !== null ? cause.message : undefined) { + msg += "\t cause: " + cause.message + " "; + } + if (typeof cause !== "undefined" && cause !== null ? cause.stack : undefined) { + msg += "\n stack: " + cause.stack + " "; + } + throw new Error(msg); + } + }]); + + return ErrorWithCause; +}(); + +module.exports = ErrorWithCause; +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/operations.js":[function(require,module,exports){ +"use strict"; + +var types = require("./types"); +var SerializerImpl = require("./serializer"); + +var uint8 = types.uint8, + uint16 = types.uint16, + uint32 = types.uint32, + int64 = types.int64, + uint64 = types.uint64, + string = types.string, + bytes = types.bytes, + bool = types.bool, + array = types.array, + fixed_array = types.fixed_array, + protocol_id_type = types.protocol_id_type, + object_id_type = types.object_id_type, + vote_id = types.vote_id, + future_extensions = types.future_extensions, + static_variant = types.static_variant, + map = types.map, + set = types.set, + public_key = types.public_key, + address = types.address, + time_point_sec = types.time_point_sec, + optional = types.optional, + variant = types.variant, + variant_object = types.variant_object, + enumeration = types.enumeration, + sha256 = types.sha256; + + +future_extensions = types.void; + +/* +When updating generated code +Replace: operation = static_variant [ +with: operation.st_operations = [ + +Delete: +public_key = new Serializer( + "public_key" + key_data: bytes 33 +) + +*/ +// Place-holder, their are dependencies on "operation" .. The final list of +// operations is not avialble until the very end of the generated code. +// See: operation.st_operations = ... +var operation = static_variant(); +module.exports["operation"] = operation; + +// For module.exports +var Serializer = function Serializer(operation_name, serilization_types_object) { + var s = new SerializerImpl(operation_name, serilization_types_object); + return module.exports[operation_name] = s; +}; + +// Custom-types follow Generated code: + +// ## Generated code follows +// # programs/js_operation_serializer > npm i -g decaffeinate +// ## ------------------------------- +var transfer_operation_fee_parameters = new Serializer("transfer_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var limit_order_create_operation_fee_parameters = new Serializer("limit_order_create_operation_fee_parameters", { fee: uint64 }); + +var limit_order_cancel_operation_fee_parameters = new Serializer("limit_order_cancel_operation_fee_parameters", { fee: uint64 }); + +var call_order_update_operation_fee_parameters = new Serializer("call_order_update_operation_fee_parameters", { fee: uint64 }); + +var fill_order_operation_fee_parameters = new Serializer("fill_order_operation_fee_parameters"); + +var account_create_operation_fee_parameters = new Serializer("account_create_operation_fee_parameters", { basic_fee: uint64, + premium_fee: uint64, + price_per_kbyte: uint32 }); + +var account_update_operation_fee_parameters = new Serializer("account_update_operation_fee_parameters", { fee: int64, + price_per_kbyte: uint32 }); + +var account_whitelist_operation_fee_parameters = new Serializer("account_whitelist_operation_fee_parameters", { fee: int64 }); + +var account_upgrade_operation_fee_parameters = new Serializer("account_upgrade_operation_fee_parameters", { membership_annual_fee: uint64, + membership_lifetime_fee: uint64 }); + +var account_transfer_operation_fee_parameters = new Serializer("account_transfer_operation_fee_parameters", { fee: uint64 }); + +var asset_create_operation_fee_parameters = new Serializer("asset_create_operation_fee_parameters", { symbol3: uint64, + symbol4: uint64, + long_symbol: uint64, + price_per_kbyte: uint32 }); + +var asset_update_operation_fee_parameters = new Serializer("asset_update_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var asset_update_bitasset_operation_fee_parameters = new Serializer("asset_update_bitasset_operation_fee_parameters", { fee: uint64 }); + +var asset_update_feed_producers_operation_fee_parameters = new Serializer("asset_update_feed_producers_operation_fee_parameters", { fee: uint64 }); + +var asset_issue_operation_fee_parameters = new Serializer("asset_issue_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var asset_reserve_operation_fee_parameters = new Serializer("asset_reserve_operation_fee_parameters", { fee: uint64 }); + +var asset_fund_fee_pool_operation_fee_parameters = new Serializer("asset_fund_fee_pool_operation_fee_parameters", { fee: uint64 }); + +var asset_settle_operation_fee_parameters = new Serializer("asset_settle_operation_fee_parameters", { fee: uint64 }); + +var asset_global_settle_operation_fee_parameters = new Serializer("asset_global_settle_operation_fee_parameters", { fee: uint64 }); + +var asset_publish_feed_operation_fee_parameters = new Serializer("asset_publish_feed_operation_fee_parameters", { fee: uint64 }); + +var witness_create_operation_fee_parameters = new Serializer("witness_create_operation_fee_parameters", { fee: uint64 }); + +var witness_update_operation_fee_parameters = new Serializer("witness_update_operation_fee_parameters", { fee: int64 }); + +var proposal_create_operation_fee_parameters = new Serializer("proposal_create_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var proposal_update_operation_fee_parameters = new Serializer("proposal_update_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var proposal_delete_operation_fee_parameters = new Serializer("proposal_delete_operation_fee_parameters", { fee: uint64 }); + +var withdraw_permission_create_operation_fee_parameters = new Serializer("withdraw_permission_create_operation_fee_parameters", { fee: uint64 }); + +var withdraw_permission_update_operation_fee_parameters = new Serializer("withdraw_permission_update_operation_fee_parameters", { fee: uint64 }); + +var withdraw_permission_claim_operation_fee_parameters = new Serializer("withdraw_permission_claim_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var withdraw_permission_delete_operation_fee_parameters = new Serializer("withdraw_permission_delete_operation_fee_parameters", { fee: uint64 }); + +var committee_member_create_operation_fee_parameters = new Serializer("committee_member_create_operation_fee_parameters", { fee: uint64 }); + +var committee_member_update_operation_fee_parameters = new Serializer("committee_member_update_operation_fee_parameters", { fee: uint64 }); + +var committee_member_update_global_parameters_operation_fee_parameters = new Serializer("committee_member_update_global_parameters_operation_fee_parameters", { fee: uint64 }); + +var vesting_balance_create_operation_fee_parameters = new Serializer("vesting_balance_create_operation_fee_parameters", { fee: uint64 }); + +var vesting_balance_withdraw_operation_fee_parameters = new Serializer("vesting_balance_withdraw_operation_fee_parameters", { fee: uint64 }); + +var worker_create_operation_fee_parameters = new Serializer("worker_create_operation_fee_parameters", { fee: uint64 }); + +var custom_operation_fee_parameters = new Serializer("custom_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var assert_operation_fee_parameters = new Serializer("assert_operation_fee_parameters", { fee: uint64 }); + +var balance_claim_operation_fee_parameters = new Serializer("balance_claim_operation_fee_parameters"); + +var override_transfer_operation_fee_parameters = new Serializer("override_transfer_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var transfer_to_blind_operation_fee_parameters = new Serializer("transfer_to_blind_operation_fee_parameters", { fee: uint64, + price_per_output: uint32 }); + +var blind_transfer_operation_fee_parameters = new Serializer("blind_transfer_operation_fee_parameters", { fee: uint64, + price_per_output: uint32 }); + +var transfer_from_blind_operation_fee_parameters = new Serializer("transfer_from_blind_operation_fee_parameters", { fee: uint64 }); + +var asset_settle_cancel_operation_fee_parameters = new Serializer("asset_settle_cancel_operation_fee_parameters"); + +var asset_claim_fees_operation_fee_parameters = new Serializer("asset_claim_fees_operation_fee_parameters", { fee: uint64 }); + +var fba_distribute_operation_fee_parameters = new Serializer("fba_distribute_operation_fee_parameters", {}); + +var tournament_create_operation_fee_parameters = new Serializer("tournament_create_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var tournament_join_operation_fee_parameters = new Serializer("tournament_join_operation_fee_parameters", { fee: uint64 }); + +var fee_parameters = static_variant([transfer_operation_fee_parameters, limit_order_create_operation_fee_parameters, limit_order_cancel_operation_fee_parameters, call_order_update_operation_fee_parameters, fill_order_operation_fee_parameters, account_create_operation_fee_parameters, account_update_operation_fee_parameters, account_whitelist_operation_fee_parameters, account_upgrade_operation_fee_parameters, account_transfer_operation_fee_parameters, asset_create_operation_fee_parameters, asset_update_operation_fee_parameters, asset_update_bitasset_operation_fee_parameters, asset_update_feed_producers_operation_fee_parameters, asset_issue_operation_fee_parameters, asset_reserve_operation_fee_parameters, asset_fund_fee_pool_operation_fee_parameters, asset_settle_operation_fee_parameters, asset_global_settle_operation_fee_parameters, asset_publish_feed_operation_fee_parameters, witness_create_operation_fee_parameters, witness_update_operation_fee_parameters, proposal_create_operation_fee_parameters, proposal_update_operation_fee_parameters, proposal_delete_operation_fee_parameters, withdraw_permission_create_operation_fee_parameters, withdraw_permission_update_operation_fee_parameters, withdraw_permission_claim_operation_fee_parameters, withdraw_permission_delete_operation_fee_parameters, committee_member_create_operation_fee_parameters, committee_member_update_operation_fee_parameters, committee_member_update_global_parameters_operation_fee_parameters, vesting_balance_create_operation_fee_parameters, vesting_balance_withdraw_operation_fee_parameters, worker_create_operation_fee_parameters, custom_operation_fee_parameters, assert_operation_fee_parameters, balance_claim_operation_fee_parameters, override_transfer_operation_fee_parameters, transfer_to_blind_operation_fee_parameters, blind_transfer_operation_fee_parameters, transfer_from_blind_operation_fee_parameters, asset_settle_cancel_operation_fee_parameters, asset_claim_fees_operation_fee_parameters, fba_distribute_operation_fee_parameters, tournament_create_operation_fee_parameters, tournament_join_operation_fee_parameters]); + +var fee_schedule = new Serializer("fee_schedule", { parameters: set(fee_parameters), + scale: uint32 }); + +var void_result = new Serializer("void_result"); + +var asset = new Serializer("asset", { amount: int64, + asset_id: protocol_id_type("asset") }); + +var operation_result = static_variant([void_result, object_id_type, asset]); + +var processed_transaction = new Serializer("processed_transaction", { ref_block_num: uint16, + ref_block_prefix: uint32, + expiration: time_point_sec, + operations: array(operation), + extensions: set(future_extensions), + signatures: array(bytes(65)), + operation_results: array(operation_result) }); + +var signed_block = new Serializer("signed_block", { previous: bytes(20), + timestamp: time_point_sec, + witness: protocol_id_type("witness"), + transaction_merkle_root: bytes(20), + extensions: set(future_extensions), + witness_signature: bytes(65), + transactions: array(processed_transaction) }); + +var block_header = new Serializer("block_header", { previous: bytes(20), + timestamp: time_point_sec, + witness: protocol_id_type("witness"), + transaction_merkle_root: bytes(20), + extensions: set(future_extensions) }); + +var signed_block_header = new Serializer("signed_block_header", { previous: bytes(20), + timestamp: time_point_sec, + witness: protocol_id_type("witness"), + transaction_merkle_root: bytes(20), + extensions: set(future_extensions), + witness_signature: bytes(65) }); + +var memo_data = new Serializer("memo_data", { from: public_key, + to: public_key, + nonce: uint64, + message: bytes() }); + +var transfer = new Serializer("transfer", { fee: asset, + from: protocol_id_type("account"), + to: protocol_id_type("account"), + amount: asset, + memo: optional(memo_data), + extensions: set(future_extensions) }); + +var limit_order_create = new Serializer("limit_order_create", { fee: asset, + seller: protocol_id_type("account"), + amount_to_sell: asset, + min_to_receive: asset, + expiration: time_point_sec, + fill_or_kill: bool, + extensions: set(future_extensions) }); + +var limit_order_cancel = new Serializer("limit_order_cancel", { fee: asset, + fee_paying_account: protocol_id_type("account"), + order: protocol_id_type("limit_order"), + extensions: set(future_extensions) }); + +var call_order_update = new Serializer("call_order_update", { fee: asset, + funding_account: protocol_id_type("account"), + delta_collateral: asset, + delta_debt: asset, + extensions: set(future_extensions) }); + +var fill_order = new Serializer("fill_order", { fee: asset, + order_id: object_id_type, + account_id: protocol_id_type("account"), + pays: asset, + receives: asset }); + +var authority = new Serializer("authority", { weight_threshold: uint32, + account_auths: map(protocol_id_type("account"), uint16), + key_auths: map(public_key, uint16), + address_auths: map(address, uint16) }); + +var account_options = new Serializer("account_options", { memo_key: public_key, + voting_account: protocol_id_type("account"), + num_witness: uint16, + num_committee: uint16, + votes: set(vote_id), + extensions: set(future_extensions) }); + +var account_create = new Serializer("account_create", { fee: asset, + registrar: protocol_id_type("account"), + referrer: protocol_id_type("account"), + referrer_percent: uint16, + name: string, + owner: authority, + active: authority, + options: account_options, + extensions: set(future_extensions) }); + +var account_update = new Serializer("account_update", { fee: asset, + account: protocol_id_type("account"), + owner: optional(authority), + active: optional(authority), + new_options: optional(account_options), + extensions: set(future_extensions) }); + +var account_whitelist = new Serializer("account_whitelist", { fee: asset, + authorizing_account: protocol_id_type("account"), + account_to_list: protocol_id_type("account"), + new_listing: uint8, + extensions: set(future_extensions) }); + +var account_upgrade = new Serializer("account_upgrade", { fee: asset, + account_to_upgrade: protocol_id_type("account"), + upgrade_to_lifetime_member: bool, + extensions: set(future_extensions) }); + +var account_transfer = new Serializer("account_transfer", { fee: asset, + account_id: protocol_id_type("account"), + new_owner: protocol_id_type("account"), + extensions: set(future_extensions) }); + +var price = new Serializer("price", { base: asset, + quote: asset }); + +var asset_options = new Serializer("asset_options", { max_supply: int64, + market_fee_percent: uint16, + max_market_fee: int64, + issuer_permissions: uint16, + flags: uint16, + core_exchange_rate: price, + whitelist_authorities: set(protocol_id_type("account")), + blacklist_authorities: set(protocol_id_type("account")), + whitelist_markets: set(protocol_id_type("asset")), + blacklist_markets: set(protocol_id_type("asset")), + description: string, + extensions: set(future_extensions) }); + +var bitasset_options = new Serializer("bitasset_options", { feed_lifetime_sec: uint32, + minimum_feeds: uint8, + force_settlement_delay_sec: uint32, + force_settlement_offset_percent: uint16, + maximum_force_settlement_volume: uint16, + short_backing_asset: protocol_id_type("asset"), + extensions: set(future_extensions) }); + +var asset_create = new Serializer("asset_create", { fee: asset, + issuer: protocol_id_type("account"), + symbol: string, + precision: uint8, + common_options: asset_options, + bitasset_opts: optional(bitasset_options), + is_prediction_market: bool, + extensions: set(future_extensions) }); + +var asset_update = new Serializer("asset_update", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_update: protocol_id_type("asset"), + new_issuer: optional(protocol_id_type("account")), + new_options: asset_options, + extensions: set(future_extensions) }); + +var asset_update_bitasset = new Serializer("asset_update_bitasset", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_update: protocol_id_type("asset"), + new_options: bitasset_options, + extensions: set(future_extensions) }); + +var asset_update_feed_producers = new Serializer("asset_update_feed_producers", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_update: protocol_id_type("asset"), + new_feed_producers: set(protocol_id_type("account")), + extensions: set(future_extensions) }); + +var asset_issue = new Serializer("asset_issue", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_issue: asset, + issue_to_account: protocol_id_type("account"), + memo: optional(memo_data), + extensions: set(future_extensions) }); + +var asset_reserve = new Serializer("asset_reserve", { fee: asset, + payer: protocol_id_type("account"), + amount_to_reserve: asset, + extensions: set(future_extensions) }); + +var asset_fund_fee_pool = new Serializer("asset_fund_fee_pool", { fee: asset, + from_account: protocol_id_type("account"), + asset_id: protocol_id_type("asset"), + amount: int64, + extensions: set(future_extensions) }); + +var asset_settle = new Serializer("asset_settle", { fee: asset, + account: protocol_id_type("account"), + amount: asset, + extensions: set(future_extensions) }); + +var asset_global_settle = new Serializer("asset_global_settle", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_settle: protocol_id_type("asset"), + settle_price: price, + extensions: set(future_extensions) }); + +var price_feed = new Serializer("price_feed", { settlement_price: price, + maintenance_collateral_ratio: uint16, + maximum_short_squeeze_ratio: uint16, + core_exchange_rate: price }); + +var asset_publish_feed = new Serializer("asset_publish_feed", { fee: asset, + publisher: protocol_id_type("account"), + asset_id: protocol_id_type("asset"), + feed: price_feed, + extensions: set(future_extensions) }); + +var witness_create = new Serializer("witness_create", { fee: asset, + witness_account: protocol_id_type("account"), + url: string, + block_signing_key: public_key }); + +var witness_update = new Serializer("witness_update", { fee: asset, + witness: protocol_id_type("witness"), + witness_account: protocol_id_type("account"), + new_url: optional(string), + new_signing_key: optional(public_key) }); + +var op_wrapper = new Serializer("op_wrapper", { op: operation }); + +var proposal_create = new Serializer("proposal_create", { fee: asset, + fee_paying_account: protocol_id_type("account"), + expiration_time: time_point_sec, + proposed_ops: array(op_wrapper), + review_period_seconds: optional(uint32), + extensions: set(future_extensions) }); + +var proposal_update = new Serializer("proposal_update", { fee: asset, + fee_paying_account: protocol_id_type("account"), + proposal: protocol_id_type("proposal"), + active_approvals_to_add: set(protocol_id_type("account")), + active_approvals_to_remove: set(protocol_id_type("account")), + owner_approvals_to_add: set(protocol_id_type("account")), + owner_approvals_to_remove: set(protocol_id_type("account")), + key_approvals_to_add: set(public_key), + key_approvals_to_remove: set(public_key), + extensions: set(future_extensions) }); + +var proposal_delete = new Serializer("proposal_delete", { fee: asset, + fee_paying_account: protocol_id_type("account"), + using_owner_authority: bool, + proposal: protocol_id_type("proposal"), + extensions: set(future_extensions) }); + +var withdraw_permission_create = new Serializer("withdraw_permission_create", { fee: asset, + withdraw_from_account: protocol_id_type("account"), + authorized_account: protocol_id_type("account"), + withdrawal_limit: asset, + withdrawal_period_sec: uint32, + periods_until_expiration: uint32, + period_start_time: time_point_sec }); + +var withdraw_permission_update = new Serializer("withdraw_permission_update", { fee: asset, + withdraw_from_account: protocol_id_type("account"), + authorized_account: protocol_id_type("account"), + permission_to_update: protocol_id_type("withdraw_permission"), + withdrawal_limit: asset, + withdrawal_period_sec: uint32, + period_start_time: time_point_sec, + periods_until_expiration: uint32 }); + +var withdraw_permission_claim = new Serializer("withdraw_permission_claim", { fee: asset, + withdraw_permission: protocol_id_type("withdraw_permission"), + withdraw_from_account: protocol_id_type("account"), + withdraw_to_account: protocol_id_type("account"), + amount_to_withdraw: asset, + memo: optional(memo_data) }); + +var withdraw_permission_delete = new Serializer("withdraw_permission_delete", { fee: asset, + withdraw_from_account: protocol_id_type("account"), + authorized_account: protocol_id_type("account"), + withdrawal_permission: protocol_id_type("withdraw_permission") }); + +var committee_member_create = new Serializer("committee_member_create", { fee: asset, + committee_member_account: protocol_id_type("account"), + url: string }); + +var committee_member_update = new Serializer("committee_member_update", { fee: asset, + committee_member: protocol_id_type("committee_member"), + committee_member_account: protocol_id_type("account"), + new_url: optional(string) }); + +var chain_parameters = new Serializer("chain_parameters", { current_fees: fee_schedule, + block_interval: uint8, + maintenance_interval: uint32, + maintenance_skip_slots: uint8, + committee_proposal_review_period: uint32, + maximum_transaction_size: uint32, + maximum_block_size: uint32, + maximum_time_until_expiration: uint32, + maximum_proposal_lifetime: uint32, + maximum_asset_whitelist_authorities: uint8, + maximum_asset_feed_publishers: uint8, + maximum_witness_count: uint16, + maximum_committee_count: uint16, + maximum_authority_membership: uint16, + reserve_percent_of_fee: uint16, + network_percent_of_fee: uint16, + lifetime_referrer_percent_of_fee: uint16, + cashback_vesting_period_seconds: uint32, + cashback_vesting_threshold: int64, + count_non_member_votes: bool, + allow_non_member_whitelists: bool, + witness_pay_per_block: int64, + worker_budget_per_day: int64, + max_predicate_opcode: uint16, + fee_liquidation_threshold: int64, + accounts_per_fee_scale: uint16, + account_fee_scale_bitshifts: uint8, + max_authority_depth: uint8, + extensions: set(future_extensions) }); + +var committee_member_update_global_parameters = new Serializer("committee_member_update_global_parameters", { fee: asset, + new_parameters: chain_parameters }); + +var linear_vesting_policy_initializer = new Serializer("linear_vesting_policy_initializer", { begin_timestamp: time_point_sec, + vesting_cliff_seconds: uint32, + vesting_duration_seconds: uint32 }); + +var cdd_vesting_policy_initializer = new Serializer("cdd_vesting_policy_initializer", { start_claim: time_point_sec, + vesting_seconds: uint32 }); + +var vesting_policy_initializer = static_variant([linear_vesting_policy_initializer, cdd_vesting_policy_initializer]); + +var vesting_balance_create = new Serializer("vesting_balance_create", { fee: asset, + creator: protocol_id_type("account"), + owner: protocol_id_type("account"), + amount: asset, + policy: vesting_policy_initializer }); + +var vesting_balance_withdraw = new Serializer("vesting_balance_withdraw", { fee: asset, + vesting_balance: protocol_id_type("vesting_balance"), + owner: protocol_id_type("account"), + amount: asset }); + +var refund_worker_initializer = new Serializer("refund_worker_initializer"); + +var vesting_balance_worker_initializer = new Serializer("vesting_balance_worker_initializer", { pay_vesting_period_days: uint16 }); + +var burn_worker_initializer = new Serializer("burn_worker_initializer"); + +var worker_initializer = static_variant([refund_worker_initializer, vesting_balance_worker_initializer, burn_worker_initializer]); + +var worker_create = new Serializer("worker_create", { fee: asset, + owner: protocol_id_type("account"), + work_begin_date: time_point_sec, + work_end_date: time_point_sec, + daily_pay: int64, + name: string, + url: string, + initializer: worker_initializer }); + +var custom = new Serializer("custom", { fee: asset, + payer: protocol_id_type("account"), + required_auths: set(protocol_id_type("account")), + id: uint16, + data: bytes() }); + +var account_name_eq_lit_predicate = new Serializer("account_name_eq_lit_predicate", { account_id: protocol_id_type("account"), + name: string }); + +var asset_symbol_eq_lit_predicate = new Serializer("asset_symbol_eq_lit_predicate", { asset_id: protocol_id_type("asset"), + symbol: string }); + +var block_id_predicate = new Serializer("block_id_predicate", { id: bytes(20) }); + +var predicate = static_variant([account_name_eq_lit_predicate, asset_symbol_eq_lit_predicate, block_id_predicate]); + +var assert = new Serializer("assert", { fee: asset, + fee_paying_account: protocol_id_type("account"), + predicates: array(predicate), + required_auths: set(protocol_id_type("account")), + extensions: set(future_extensions) }); + +var balance_claim = new Serializer("balance_claim", { fee: asset, + deposit_to_account: protocol_id_type("account"), + balance_to_claim: protocol_id_type("balance"), + balance_owner_key: public_key, + total_claimed: asset }); + +var override_transfer = new Serializer("override_transfer", { fee: asset, + issuer: protocol_id_type("account"), + from: protocol_id_type("account"), + to: protocol_id_type("account"), + amount: asset, + memo: optional(memo_data), + extensions: set(future_extensions) }); + +var stealth_confirmation = new Serializer("stealth_confirmation", { one_time_key: public_key, + to: optional(public_key), + encrypted_memo: bytes() }); + +var blind_output = new Serializer("blind_output", { commitment: bytes(33), + range_proof: bytes(), + owner: authority, + stealth_memo: optional(stealth_confirmation) }); + +var transfer_to_blind = new Serializer("transfer_to_blind", { fee: asset, + amount: asset, + from: protocol_id_type("account"), + blinding_factor: bytes(32), + outputs: array(blind_output) }); + +var blind_input = new Serializer("blind_input", { commitment: bytes(33), + owner: authority }); + +var blind_transfer = new Serializer("blind_transfer", { fee: asset, + inputs: array(blind_input), + outputs: array(blind_output) }); + +var transfer_from_blind = new Serializer("transfer_from_blind", { fee: asset, + amount: asset, + to: protocol_id_type("account"), + blinding_factor: bytes(32), + inputs: array(blind_input) }); + +var asset_settle_cancel = new Serializer("asset_settle_cancel", { fee: asset, + settlement: protocol_id_type("force_settlement"), + account: protocol_id_type("account"), + amount: asset, + extensions: set(future_extensions) }); + +var asset_claim_fees = new Serializer("asset_claim_fees", { fee: asset, + issuer: protocol_id_type("account"), + amount_to_claim: asset, + extensions: set(future_extensions) }); + +var fba_distribute = new Serializer("fba_distribute", { fee: asset, + account_id: protocol_id_type("account"), + fba_id: protocol_id_type("fba_accumulator"), + amount: int64 }); + +var dividend_asset_options = new Serializer("dividend_asset_options", { next_payout_time: optional(time_point_sec), + payout_interval: optional(uint32), + minimum_fee_percentage: uint64, + minimum_distribution_interval: optional(uint32), + extensions: set(future_extensions) }); + +var asset_update_dividend = new Serializer("asset_update_dividend", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_update: protocol_id_type("asset"), + new_options: dividend_asset_options, + extensions: set(future_extensions) }); + +var rock_paper_scissors_game_options = new Serializer("rock_paper_scissors_game_options", { insurance_enabled: bool, + time_per_commit_move: uint32, + time_per_reveal_move: uint32, + number_of_gestures: uint8 }); + +var game_specific_details = static_variant([rock_paper_scissors_game_options]); + +var tournament_options = new Serializer("tournament_options", { + type_of_game: uint16, + registration_deadline: time_point_sec, + number_of_players: uint32, + buy_in: asset, + whitelist: set(protocol_id_type("account")), + start_time: optional(time_point_sec), + start_delay: optional(uint32), + round_delay: uint32, + number_of_wins: uint32, + meta: variant_object, + game_options: game_specific_details +}); + +var tournament_create = new Serializer("tournament_create", { fee: asset, + creator: protocol_id_type("account"), + options: tournament_options, + extensions: set(future_extensions) }); + +var tournament_join = new Serializer("tournament_join", { fee: asset, + payer_account_id: protocol_id_type("account"), + player_account_id: protocol_id_type("account"), + tournament_id: protocol_id_type("tournament"), + buy_in: asset, + extensions: set(future_extensions) }); + +var rock_paper_scissors_gesture = enumeration(["rock", "paper", "scissors", "spock", "lizard"]); + +var rock_paper_scissors_throw_commit = new Serializer("rock_paper_scissors_throw_commit", { nonce1: uint64, + throw_hash: sha256 }); + +var rock_paper_scissors_throw_reveal = new Serializer("rock_paper_scissors_throw_reveal", { nonce2: uint64, + gesture: rock_paper_scissors_gesture }); + +var game_specific_moves = static_variant([rock_paper_scissors_throw_commit, rock_paper_scissors_throw_reveal]); + +var game_move = new Serializer("game_move", { fee: asset, + game_id: protocol_id_type("game"), + player_account_id: protocol_id_type("account"), + move: game_specific_moves, + extensions: set(future_extensions) }); + +operation.st_operations = [transfer, limit_order_create, limit_order_cancel, call_order_update, fill_order, account_create, account_update, account_whitelist, account_upgrade, account_transfer, asset_create, asset_update, asset_update_bitasset, asset_update_feed_producers, asset_issue, asset_reserve, asset_fund_fee_pool, asset_settle, asset_global_settle, asset_publish_feed, witness_create, witness_update, proposal_create, proposal_update, proposal_delete, withdraw_permission_create, withdraw_permission_update, withdraw_permission_claim, withdraw_permission_delete, committee_member_create, committee_member_update, committee_member_update_global_parameters, vesting_balance_create, vesting_balance_withdraw, worker_create, custom, assert, balance_claim, override_transfer, transfer_to_blind, blind_transfer, transfer_from_blind, asset_settle_cancel, asset_claim_fees, fba_distribute, tournament_create, tournament_join, game_move, asset_update_dividend]; + +var transaction = new Serializer("transaction", { ref_block_num: uint16, + ref_block_prefix: uint32, + expiration: time_point_sec, + operations: array(operation), + extensions: set(future_extensions) }); + +var signed_transaction = new Serializer("signed_transaction", { ref_block_num: uint16, + ref_block_prefix: uint32, + expiration: time_point_sec, + operations: array(operation), + extensions: set(future_extensions), + signatures: array(bytes(65)) }); +//# ------------------------------- +//# Generated code end +//# ------------------------------- + +// Custom Types + +var stealth_memo_data = new Serializer("stealth_memo_data", { + from: optional(public_key), + amount: asset, + blinding_factor: bytes(32), + commitment: bytes(33), + check: uint32 +}); +// var stealth_confirmation = new Serializer( +// "stealth_confirmation", { +// one_time_key: public_key, +// to: optional( public_key ), +// encrypted_memo: stealth_memo_data +// }) +},{"./serializer":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/serializer.js","./types":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/types.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/serializer.js":[function(require,module,exports){ +(function (process,Buffer){ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ByteBuffer = require('bytebuffer'); +var EC = require('./error_with_cause'); + +var HEX_DUMP = process.env.npm_config__graphene_serializer_hex_dump; + +var Serializer = function () { + function Serializer(operation_name, types) { + _classCallCheck(this, Serializer); + + this.operation_name = operation_name; + this.types = types; + if (this.types) this.keys = Object.keys(this.types); + + Serializer.printDebug = true; + } + + _createClass(Serializer, [{ + key: 'fromByteBuffer', + value: function fromByteBuffer(b) { + var object = {}; + var field = null; + try { + var iterable = this.keys; + for (var i = 0, field; i < iterable.length; i++) { + field = iterable[i]; + var type = this.types[field]; + try { + if (HEX_DUMP) { + if (type.operation_name) { + console.error(type.operation_name); + } else { + var o1 = b.offset; + type.fromByteBuffer(b); + var o2 = b.offset; + b.offset = o1; + //b.reset() + var _b = b.copy(o1, o2); + console.error(this.operation_name + '.' + field + '\t', _b.toHex()); + } + } + object[field] = type.fromByteBuffer(b); + } catch (e) { + if (Serializer.printDebug) { + console.error('Error reading ' + this.operation_name + '.' + field + ' in data:'); + b.printDebug(); + } + throw e; + } + } + } catch (error) { + EC.throw(this.operation_name + '.' + field, error); + } + + return object; + } + }, { + key: 'appendByteBuffer', + value: function appendByteBuffer(b, object) { + var field = null; + try { + var iterable = this.keys; + for (var i = 0, field; i < iterable.length; i++) { + field = iterable[i]; + var type = this.types[field]; + type.appendByteBuffer(b, object[field]); + } + } catch (error) { + try { + EC.throw(this.operation_name + '.' + field + " = " + JSON.stringify(object[field]), error); + } catch (e) { + // circular ref + EC.throw(this.operation_name + '.' + field + " = " + object[field], error); + } + } + return; + } + }, { + key: 'fromObject', + value: function fromObject(serialized_object) { + var result = {}; + var field = null; + try { + var iterable = this.keys; + for (var i = 0, field; i < iterable.length; i++) { + field = iterable[i]; + var type = this.types[field]; + var value = serialized_object[field]; + //DEBUG value = value.resolve if value.resolve + //DEBUG console.log('... value',field,value) + var object = type.fromObject(value); + result[field] = object; + } + } catch (error) { + EC.throw(this.operation_name + '.' + field, error); + } + + return result; + } + + /** + @arg {boolean} [debug.use_default = false] - more template friendly + @arg {boolean} [debug.annotate = false] - add user-friendly information + */ + + }, { + key: 'toObject', + value: function toObject() { + var serialized_object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { use_default: false, annotate: false }; + + var result = {}; + var field = null; + try { + if (!this.types) return result; + + var iterable = this.keys; + for (var i = 0, field; i < iterable.length; i++) { + field = iterable[i]; + var type = this.types[field]; + var object = type.toObject(typeof serialized_object !== "undefined" && serialized_object !== null ? serialized_object[field] : undefined, debug); + result[field] = object; + if (HEX_DUMP) { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + type.appendByteBuffer(b, typeof serialized_object !== "undefined" && serialized_object !== null ? serialized_object[field] : undefined); + b = b.copy(0, b.offset); + console.error(this.operation_name + '.' + field, b.toHex()); + } + } + } catch (error) { + EC.throw(this.operation_name + '.' + field, error); + } + + return result; + } + + /** Sort by the first element in a operation */ + + }, { + key: 'compare', + value: function compare(a, b) { + + var first_key = this.keys[0]; + var first_type = this.types[first_key]; + + var valA = a[first_key]; + var valB = b[first_key]; + + if (first_type.compare) return first_type.compare(valA, valB); + + if (typeof valA === "number" && typeof valB === "number") return valA - valB; + + var encoding = void 0; + if (Buffer.isBuffer(valA) && Buffer.isBuffer(valB)) { + // A binary string compare does not work. If localeCompare is well supported that could replace HEX. Performanance is very good so comparing HEX works. + encoding = "hex"; + } + + var strA = valA.toString(encoding); + var strB = valB.toString(encoding); + return strA > strB ? 1 : strA < strB ? -1 : 0; + } + + // + + }, { + key: 'fromHex', + value: function fromHex(hex) { + var b = ByteBuffer.fromHex(hex, ByteBuffer.LITTLE_ENDIAN); + return this.fromByteBuffer(b); + } + }, { + key: 'fromBuffer', + value: function fromBuffer(buffer) { + var b = ByteBuffer.fromBinary(buffer.toString("binary"), ByteBuffer.LITTLE_ENDIAN); + return this.fromByteBuffer(b); + } + }, { + key: 'toHex', + value: function toHex(object) { + // return this.toBuffer(object).toString("hex") + var b = this.toByteBuffer(object); + return b.toHex(); + } + }, { + key: 'toByteBuffer', + value: function toByteBuffer(object) { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + this.appendByteBuffer(b, object); + return b.copy(0, b.offset); + } + }, { + key: 'toBuffer', + value: function toBuffer(object) { + return new Buffer(this.toByteBuffer(object).toBinary(), 'binary'); + } + }]); + + return Serializer; +}(); + +module.exports = Serializer; +}).call(this,require('_process'),require("buffer").Buffer) + +},{"./error_with_cause":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/error_with_cause.js","_process":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","bytebuffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bytebuffer/dist/bytebuffer.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/template.js":[function(require,module,exports){ +"use strict"; + +/** Console print any transaction object with zero default values. */ +module.exports = function template(op) { + + var object = op.toObject(void 0, { use_default: true, annotate: true }); + + // visual (with descriptions) + console.error(JSON.stringify(object, null, 4)); + + // usable in a copy-paste + + object = op.toObject(void 0, { use_default: true, annotate: false }); + + // copy-paste one-lineer + console.error(JSON.stringify(object)); +}; +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/types.js":[function(require,module,exports){ +(function (process,Buffer){ +'use strict'; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +// Low-level types that make up operations + +var v = require('./SerializerValidation'); +var fp = require('./FastParser'); + +var ChainTypes = require("../../chain/src/ChainTypes"); +var ObjectId = require("../../chain/src/ObjectId"); + +var _require = require("../../ecc"), + PublicKey = _require.PublicKey, + Address = _require.Address; + +var _require2 = require("peerplaysjs-ws"), + ChainConfig = _require2.ChainConfig; + +var Types = {}; +module.exports = Types; + +var HEX_DUMP = process.env.npm_config__graphene_serializer_hex_dump; + +Types.uint8 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint8(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.require_range(0, 0xFF, object, 'uint8 ' + object); + b.writeUint8(object); + return; + }, + fromObject: function fromObject(object) { + v.require_range(0, 0xFF, object, 'uint8 ' + object); + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return 0; + } + v.require_range(0, 0xFF, object, 'uint8 ' + object); + return parseInt(object); + } +}; + +Types.uint16 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint16(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.require_range(0, 0xFFFF, object, 'uint16 ' + object); + b.writeUint16(object); + return; + }, + fromObject: function fromObject(object) { + v.require_range(0, 0xFFFF, object, 'uint16 ' + object); + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return 0; + } + v.require_range(0, 0xFFFF, object, 'uint16 ' + object); + return parseInt(object); + } +}; + +Types.uint32 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint32(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.require_range(0, 0xFFFFFFFF, object, 'uint32 ' + object); + b.writeUint32(object); + return; + }, + fromObject: function fromObject(object) { + v.require_range(0, 0xFFFFFFFF, object, 'uint32 ' + object); + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return 0; + } + v.require_range(0, 0xFFFFFFFF, object, 'uint32 ' + object); + return parseInt(object); + } +}; + +var MIN_SIGNED_32 = -1 * Math.pow(2, 31); +var MAX_SIGNED_32 = Math.pow(2, 31) - 1; + +Types.varint32 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readVarint32(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.require_range(MIN_SIGNED_32, MAX_SIGNED_32, object, 'uint32 ' + object); + b.writeVarint32(object); + return; + }, + fromObject: function fromObject(object) { + v.require_range(MIN_SIGNED_32, MAX_SIGNED_32, object, 'uint32 ' + object); + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return 0; + } + v.require_range(MIN_SIGNED_32, MAX_SIGNED_32, object, 'uint32 ' + object); + return parseInt(object); + } +}; + +Types.int64 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readInt64(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + b.writeInt64(v.to_long(object)); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + return v.to_long(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return "0"; + } + v.required(object); + return v.to_long(object).toString(); + } +}; + +Types.uint64 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint64(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + b.writeUint64(v.to_ulong(v.unsigned(object))); + return; + }, + fromObject: function fromObject(object) { + return v.to_ulong(v.unsigned(object)); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return "0"; + } + return v.to_ulong(object).toString(); + } +}; + +Types.string = { + fromByteBuffer: function fromByteBuffer(b) { + var b_copy; + var len = b.readVarint32(); + b_copy = b.copy(b.offset, b.offset + len), b.skip(len); + return new Buffer(b_copy.toBinary(), 'binary'); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + b.writeVarint32(object.length); + b.append(object.toString('binary'), 'binary'); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + return new Buffer(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return ""; + } + return object.toString(); + } +}; + +Types.bytes = function (size) { + return { + fromByteBuffer: function fromByteBuffer(b) { + if (size === undefined) { + var b_copy; + var len = b.readVarint32(); + b_copy = b.copy(b.offset, b.offset + len), b.skip(len); + return new Buffer(b_copy.toBinary(), 'binary'); + } else { + b_copy = b.copy(b.offset, b.offset + size), b.skip(size); + return new Buffer(b_copy.toBinary(), 'binary'); + } + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + if (typeof object === "string") object = new Buffer(object, "hex"); + + if (size === undefined) { + b.writeVarint32(object.length); + } + b.append(object.toString('binary'), 'binary'); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + if (Buffer.isBuffer(object)) return object; + + return new Buffer(object, 'hex'); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + var zeros = function zeros(num) { + return new Array(num).join("00"); + }; + return zeros(size); + } + v.required(object); + return object.toString('hex'); + } + }; +}; + +Types.bool = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint8() === 1; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + // supports boolean or integer + b.writeUint8(JSON.parse(object) ? 1 : 0); + return; + }, + fromObject: function fromObject(object) { + return JSON.parse(object) ? true : false; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return false; + } + return JSON.parse(object) ? true : false; + } +}; + +Types.void = { + fromByteBuffer: function fromByteBuffer(b) { + throw new Error("(void) undefined type"); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + throw new Error("(void) undefined type"); + }, + fromObject: function fromObject(object) { + throw new Error("(void) undefined type"); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return undefined; + } + throw new Error("(void) undefined type"); + } +}; + +Types.array = function (st_operation) { + return { + fromByteBuffer: function fromByteBuffer(b) { + var size = b.readVarint32(); + if (HEX_DUMP) { + console.log("varint32 size = " + size.toString(16)); + } + var result = []; + for (var i = 0; 0 < size ? i < size : i > size; 0 < size ? i++ : i++) { + result.push(st_operation.fromByteBuffer(b)); + } + return sortOperation(result, st_operation); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + object = sortOperation(object, st_operation); + b.writeVarint32(object.length); + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + st_operation.appendByteBuffer(b, o); + } + }, + fromObject: function fromObject(object) { + v.required(object); + object = sortOperation(object, st_operation); + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push(st_operation.fromObject(o)); + } + return result; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return [st_operation.toObject(object, debug)]; + } + v.required(object); + object = sortOperation(object, st_operation); + + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push(st_operation.toObject(o, debug)); + } + return result; + } + }; +}; + +Types.time_point_sec = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint32(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + if (typeof object !== "number") object = Types.time_point_sec.fromObject(object); + + b.writeUint32(object); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + + if (typeof object === "number") return object; + + if (object.getTime) return Math.floor(object.getTime() / 1000); + + if (typeof object !== "string") throw new Error("Unknown date type: " + object); + + // if(typeof object === "string" && !/Z$/.test(object)) + // object = object + "Z" + + return Math.floor(new Date(object).getTime() / 1000); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) return new Date(0).toISOString().split('.')[0]; + + v.required(object); + + if (typeof object === "string") return object; + + if (object.getTime) return object.toISOString().split('.')[0]; + + var int = parseInt(object); + v.require_range(0, 0xFFFFFFFF, int, 'uint32 ' + object); + return new Date(int * 1000).toISOString().split('.')[0]; + } +}; + +Types.set = function (st_operation) { + return { + validate: function validate(array) { + var dup_map = {}; + for (var i = 0, o; i < array.length; i++) { + o = array[i]; + var ref; + if (ref = typeof o === 'undefined' ? 'undefined' : _typeof(o), ['string', 'number'].indexOf(ref) >= 0) { + if (dup_map[o] !== undefined) { + throw new Error("duplicate (set)"); + } + dup_map[o] = true; + } + } + return sortOperation(array, st_operation); + }, + fromByteBuffer: function fromByteBuffer(b) { + var size = b.readVarint32(); + if (HEX_DUMP) { + console.log("varint32 size = " + size.toString(16)); + } + return this.validate(function () { + var result = []; + for (var i = 0; 0 < size ? i < size : i > size; 0 < size ? i++ : i++) { + result.push(st_operation.fromByteBuffer(b)); + } + return result; + }()); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + if (!object) { + object = []; + } + b.writeVarint32(object.length); + var iterable = this.validate(object); + for (var i = 0, o; i < iterable.length; i++) { + o = iterable[i]; + st_operation.appendByteBuffer(b, o); + } + return; + }, + fromObject: function fromObject(object) { + if (!object) { + object = []; + } + return this.validate(function () { + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push(st_operation.fromObject(o)); + } + return result; + }()); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return [st_operation.toObject(object, debug)]; + } + if (!object) { + object = []; + } + return this.validate(function () { + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push(st_operation.toObject(o, debug)); + } + return result; + }()); + } + }; +}; + +// global_parameters_update_operation current_fees +Types.fixed_array = function (count, st_operation) { + return { + fromByteBuffer: function fromByteBuffer(b) { + var i, j, ref, results; + results = []; + for (i = j = 0, ref = count; j < ref; i = j += 1) { + results.push(st_operation.fromByteBuffer(b)); + } + return sortOperation(results, st_operation); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + var i, j, ref; + if (count !== 0) { + v.required(object); + object = sortOperation(object, st_operation); + } + for (i = j = 0, ref = count; j < ref; i = j += 1) { + st_operation.appendByteBuffer(b, object[i]); + } + }, + fromObject: function fromObject(object) { + var i, j, ref, results; + if (count !== 0) { + v.required(object); + } + results = []; + for (i = j = 0, ref = count; j < ref; i = j += 1) { + results.push(st_operation.fromObject(object[i])); + } + return results; + }, + toObject: function toObject(object, debug) { + var i, j, k, ref, ref1, results, results1; + if (debug == null) { + debug = {}; + } + if (debug.use_default && object === void 0) { + results = []; + for (i = j = 0, ref = count; j < ref; i = j += 1) { + results.push(st_operation.toObject(void 0, debug)); + } + return results; + } + if (count !== 0) { + v.required(object); + } + results1 = []; + for (i = k = 0, ref1 = count; k < ref1; i = k += 1) { + results1.push(st_operation.toObject(object[i], debug)); + } + return results1; + } + }; +}; + +/* Supports instance numbers (11) or object types (1.2.11). Object type +Validation is enforced when an object type is used. */ +var id_type = function id_type(reserved_spaces, object_type) { + v.required(reserved_spaces, "reserved_spaces"); + v.required(object_type, "object_type"); + return { + fromByteBuffer: function fromByteBuffer(b) { + return b.readVarint32(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + // convert 1.2.n into just n + if (/^[0-9]+\.[0-9]+\.[0-9]+$/.test(object)) { + object = v.get_instance(reserved_spaces, object_type, object); + } + b.writeVarint32(v.to_number(object)); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + if (v.is_digits(object)) { + return v.to_number(object); + } + return v.get_instance(reserved_spaces, object_type, object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var object_type_id = ChainTypes.object_type[object_type]; + if (debug.use_default && object === undefined) { + return reserved_spaces + '.' + object_type_id + '.0'; + } + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + if (/^[0-9]+\.[0-9]+\.[0-9]+$/.test(object)) { + object = v.get_instance(reserved_spaces, object_type, object); + } + + return reserved_spaces + '.' + object_type_id + '.' + object; + } + }; +}; + +Types.protocol_id_type = function (name) { + v.required(name, "name"); + return id_type(ChainTypes.reserved_spaces.protocol_ids, name); +}; + +Types.object_id_type = { + fromByteBuffer: function fromByteBuffer(b) { + return ObjectId.fromByteBuffer(b); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + object = ObjectId.fromString(object); + object.appendByteBuffer(b); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + return ObjectId.fromString(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return "0.0.0"; + } + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + object = ObjectId.fromString(object); + return object.toString(); + } +}; + +Types.vote_id = { TYPE: 0x000000FF, + ID: 0xFFFFFF00, + fromByteBuffer: function fromByteBuffer(b) { + var value = b.readUint32(); + return { + type: value & this.TYPE, + id: value & this.ID + }; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + if (object === "string") object = Types.vote_id.fromObject(object); + + var value = object.id << 8 | object.type; + b.writeUint32(value); + return; + }, + fromObject: function fromObject(object) { + v.required(object, "(type vote_id)"); + if ((typeof object === 'undefined' ? 'undefined' : _typeof(object)) === "object") { + v.required(object.type, "type"); + v.required(object.id, "id"); + return object; + } + v.require_test(/^[0-9]+:[0-9]+$/, object, 'vote_id format ' + object); + + var _object$split = object.split(':'), + _object$split2 = _slicedToArray(_object$split, 2), + type = _object$split2[0], + id = _object$split2[1]; + + v.require_range(0, 0xff, type, 'vote type ' + object); + v.require_range(0, 0xffffff, id, 'vote id ' + object); + return { type: type, id: id }; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return "0:0"; + } + v.required(object); + if (typeof object === "string") object = Types.vote_id.fromObject(object); + + return object.type + ":" + object.id; + }, + compare: function compare(a, b) { + if ((typeof a === 'undefined' ? 'undefined' : _typeof(a)) !== "object") a = Types.vote_id.fromObject(a); + if ((typeof b === 'undefined' ? 'undefined' : _typeof(b)) !== "object") b = Types.vote_id.fromObject(b); + return parseInt(a.id) - parseInt(b.id); + } +}; + +Types.optional = function (st_operation) { + v.required(st_operation, "st_operation"); + return { + fromByteBuffer: function fromByteBuffer(b) { + if (!(b.readUint8() === 1)) { + return undefined; + } + return st_operation.fromByteBuffer(b); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + if (object !== null && object !== undefined) { + b.writeUint8(1); + st_operation.appendByteBuffer(b, object); + } else { + b.writeUint8(0); + } + return; + }, + fromObject: function fromObject(object) { + if (object === undefined) { + return undefined; + } + return st_operation.fromObject(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + // toObject is only null save if use_default is true + var result_object = function () { + if (!debug.use_default && object === undefined) { + return undefined; + } else { + return st_operation.toObject(object, debug); + } + }(); + + if (debug.annotate) { + if ((typeof result_object === 'undefined' ? 'undefined' : _typeof(result_object)) === "object") { + result_object.__optional = "parent is optional"; + } else { + result_object = { __optional: result_object }; + } + } + return result_object; + } + }; +}; + +Types.static_variant = function (_st_operations) { + return { + nosort: true, + st_operations: _st_operations, + fromByteBuffer: function fromByteBuffer(b) { + var type_id = b.readVarint32(); + var st_operation = this.st_operations[type_id]; + if (HEX_DUMP) { + console.error('static_variant id 0x' + type_id.toString(16) + ' (' + type_id + ')'); + } + v.required(st_operation, 'operation ' + type_id); + return [type_id, st_operation.fromByteBuffer(b)]; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + var type_id = object[0]; + var st_operation = this.st_operations[type_id]; + v.required(st_operation, 'operation ' + type_id); + b.writeVarint32(type_id); + st_operation.appendByteBuffer(b, object[1]); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + var type_id = object[0]; + var st_operation = this.st_operations[type_id]; + v.required(st_operation, 'operation ' + type_id); + return [type_id, st_operation.fromObject(object[1])]; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return [0, this.st_operations[0].toObject(undefined, debug)]; + } + v.required(object); + var type_id = object[0]; + var st_operation = this.st_operations[type_id]; + v.required(st_operation, 'operation ' + type_id); + return [type_id, st_operation.toObject(object[1], debug)]; + } + }; +}; + +Types.map = function (key_st_operation, value_st_operation) { + return { + validate: function validate(array) { + if (!Array.isArray(array)) { + throw new Error("expecting array"); + } + var dup_map = {}; + for (var i = 0, o; i < array.length; i++) { + o = array[i]; + var ref; + if (!(o.length === 2)) { + throw new Error("expecting two elements"); + } + if (ref = _typeof(o[0]), ['number', 'string'].indexOf(ref) >= 0) { + if (dup_map[o[0]] !== undefined) { + throw new Error("duplicate (map)"); + } + dup_map[o[0]] = true; + } + } + return sortOperation(array, key_st_operation); + }, + fromByteBuffer: function fromByteBuffer(b) { + var result = []; + var end = b.readVarint32(); + for (var i = 0; 0 < end ? i < end : i > end; 0 < end ? i++ : i++) { + result.push([key_st_operation.fromByteBuffer(b), value_st_operation.fromByteBuffer(b)]); + } + return this.validate(result); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + this.validate(object); + b.writeVarint32(object.length); + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + key_st_operation.appendByteBuffer(b, o[0]); + value_st_operation.appendByteBuffer(b, o[1]); + } + return; + }, + fromObject: function fromObject(object) { + v.required(object); + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push([key_st_operation.fromObject(o[0]), value_st_operation.fromObject(o[1])]); + } + return this.validate(result); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return [[key_st_operation.toObject(undefined, debug), value_st_operation.toObject(undefined, debug)]]; + } + v.required(object); + object = this.validate(object); + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push([key_st_operation.toObject(o[0], debug), value_st_operation.toObject(o[1], debug)]); + } + return result; + } + }; +}; + +Types.public_key = { + toPublic: function toPublic(object) { + if (object.resolve !== undefined) { + object = object.resolve; + } + + if (object instanceof PublicKey) { + return object; + } + + return object == null ? object : object.Q ? object : PublicKey.fromStringOrThrow(object); + }, + fromByteBuffer: function fromByteBuffer(b) { + return fp.public_key(b); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + fp.public_key(b, Types.public_key.toPublic(object)); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + if (object.Q) { + return object; + } + return Types.public_key.toPublic(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return ChainConfig.address_prefix + "859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVM"; + } + v.required(object); + return object.toString(); + }, + compare: function compare(a, b) { + return strCmp(a.toAddressString(), b.toAddressString()); + } +}; + +Types.address = { + _to_address: function _to_address(object) { + v.required(object); + if (object.addy) { + return object; + } + return Address.fromString(object); + }, + fromByteBuffer: function fromByteBuffer(b) { + return new Address(fp.ripemd160(b)); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + fp.ripemd160(b, Types.address._to_address(object).toBuffer()); + return; + }, + fromObject: function fromObject(object) { + return Types.address._to_address(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return ChainConfig.address_prefix + "664KmHxSuQyDsfwo4WEJvWpzg1QKdg67S"; + } + return Types.address._to_address(object).toString(); + }, + compare: function compare(a, b) { + return strCmp(a.toString(), b.toString()); + } +}; + +Types.variant = { + fromByteBuffer: function fromByteBuffer(b) { + var type = b.readUint8(); + switch (type) { + case 0: + return null; + case 1: + return Types.int64.fromByteBuffer(b); + case 2: + return Types.uint64.fromByteBuffer(b); + case 3: + return b.readDouble(); + case 4: + return Types.bool.fromByteBuffer(b); + case 5: + return Types.string.fromByteBuffer(b); + case 6: + return Types.array(Types.variant).fromByteBuffer(b); + case 7: + default: + return Types.variant_object.fromByteBuffer(b); + }; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + if (typeof object == 'number') { + if (Number.isInteger(object)) { + if (object >= 0) { + b.writeUint8(2); + Types.uint64.appendByteBuffer(b, object); + } else { + b.writeUint8(1); + Types.int64.appendByteBuffer(b, object); + } + } else { + b.writeUint8(3); + b.writeDouble(Number.parseFloat(object)); + } + } else if (typeof object == 'boolean') { + b.writeUint8(4); + Types.bool.appendByteBuffer(b, object); + } else if (typeof object == 'string') { + b.writeUint8(5); + Types.string.appendByteBuffer(b, object); + } else if (typeof object == 'array') { + b.writeUint8(6); + Types.array(Types.variant).appendByteBuffer(b, object); + } else { + b.writeUint8(7); + Types.variant_object.appendByteBuffer(b, object); + } + }, + fromObject: function fromObject(object) { + return JSON.parse(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return null; + } + return JSON.parse(object); + } +}; + +Types.variant_object = { + fromByteBuffer: function fromByteBuffer(b) { + var count = b.readVarint32(); + var result = {}; + for (var i = 0; i < count; ++i) { + var key = Types.string.fromByteBuffer(b); + result[key] = Types.variant.fromByteBuffer(b); + } + return result; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + var count = 0; + for (var key in object) { + if (object.hasOwnProperty(key)) ++count; + }b.writeVarint32(count); // number of key/value pairs + for (var key in object) { + if (object.hasOwnProperty(key)) { + Types.string.appendByteBuffer(b, key); + Types.variant.appendByteBuffer(b, object[key]); + } + }return; + }, + fromObject: function fromObject(object) { + var newObject = {}; + for (var key in object) { + if (object.hasOwnProperty(key)) newObject[key] = object[key]; + }return newObject; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var newObject = {}; + for (var key in object) { + if (object.hasOwnProperty(key)) newObject[key] = object[key]; + }return newObject; + } +}; + +Types.enumeration = function (values) { + return { + fromByteBuffer: function fromByteBuffer(b) { + return values[b.readVarint32ZigZag()]; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + b.writeVarint32ZigZag(values.indexOf(object)); + return; + }, + fromObject: function fromObject(object) { + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + values[0]; + } + return object; + } + }; +}; + +Types.sha256 = Types.bytes(32); + +var strCmp = function strCmp(a, b) { + return a > b ? 1 : a < b ? -1 : 0; +}; +var firstEl = function firstEl(el) { + return Array.isArray(el) ? el[0] : el; +}; +var sortOperation = function sortOperation(array, st_operation) { + return st_operation.nosort ? array : st_operation.compare ? array.sort(function (a, b) { + return st_operation.compare(firstEl(a), firstEl(b)); + }) : // custom compare operation + array.sort(function (a, b) { + return typeof firstEl(a) === "number" && typeof firstEl(b) === "number" ? firstEl(a) - firstEl(b) : + // A binary string compare does not work. Performanance is very good so HEX is used.. localeCompare is another option. + Buffer.isBuffer(firstEl(a)) && Buffer.isBuffer(firstEl(b)) ? strCmp(firstEl(a).toString("hex"), firstEl(b).toString("hex")) : strCmp(firstEl(a).toString(), firstEl(b).toString()); + }); +}; +}).call(this,require('_process'),require("buffer").Buffer) + +},{"../../chain/src/ChainTypes":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/chain/src/ChainTypes.js","../../chain/src/ObjectId":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/chain/src/ObjectId.js","../../ecc":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/index.js","./FastParser":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/FastParser.js","./SerializerValidation":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/SerializerValidation.js","_process":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","peerplaysjs-ws":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js":[function(require,module,exports){ +(function (global){ +'use strict'; + +// compare and isBuffer taken from https://github.com/feross/buffer/blob/680e9e5e488f22aac27599a57dc844a6315928dd/index.js +// original notice: + +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +function compare(a, b) { + if (a === b) { + return 0; + } + + var x = a.length; + var y = b.length; + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i]; + y = b[i]; + break; + } + } + + if (x < y) { + return -1; + } + if (y < x) { + return 1; + } + return 0; +} +function isBuffer(b) { + if (global.Buffer && typeof global.Buffer.isBuffer === 'function') { + return global.Buffer.isBuffer(b); + } + return !!(b != null && b._isBuffer); +} + +// based on node assert, original notice: + +// http://wiki.commonjs.org/wiki/Unit_Testing/1.0 +// +// THIS IS NOT TESTED NOR LIKELY TO WORK OUTSIDE V8! +// +// Originally from narwhal.js (http://narwhaljs.org) +// Copyright (c) 2009 Thomas Robinson <280north.com> +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the 'Software'), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +var util = require('util/'); +var hasOwn = Object.prototype.hasOwnProperty; +var pSlice = Array.prototype.slice; +var functionsHaveNames = (function () { + return function foo() {}.name === 'foo'; +}()); +function pToString (obj) { + return Object.prototype.toString.call(obj); +} +function isView(arrbuf) { + if (isBuffer(arrbuf)) { + return false; + } + if (typeof global.ArrayBuffer !== 'function') { + return false; + } + if (typeof ArrayBuffer.isView === 'function') { + return ArrayBuffer.isView(arrbuf); + } + if (!arrbuf) { + return false; + } + if (arrbuf instanceof DataView) { + return true; + } + if (arrbuf.buffer && arrbuf.buffer instanceof ArrayBuffer) { + return true; + } + return false; +} +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = module.exports = ok; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +var regex = /\s*function\s+([^\(\s]*)\s*/; +// based on https://github.com/ljharb/function.prototype.name/blob/adeeeec8bfcc6068b187d7d9fb3d5bb1d3a30899/implementation.js +function getName(func) { + if (!util.isFunction(func)) { + return; + } + if (functionsHaveNames) { + return func.name; + } + var str = func.toString(); + var match = str.match(regex); + return match && match[1]; +} +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + if (options.message) { + this.message = options.message; + this.generatedMessage = false; + } else { + this.message = getMessage(this); + this.generatedMessage = true; + } + var stackStartFunction = options.stackStartFunction || fail; + if (Error.captureStackTrace) { + Error.captureStackTrace(this, stackStartFunction); + } else { + // non v8 browsers so we can have a stacktrace + var err = new Error(); + if (err.stack) { + var out = err.stack; + + // try to strip useless frames + var fn_name = getName(stackStartFunction); + var idx = out.indexOf('\n' + fn_name); + if (idx >= 0) { + // once we have located the function frame + // we need to strip out everything before it (and its line) + var next_line = out.indexOf('\n', idx + 1); + out = out.substring(next_line + 1); + } + + this.stack = out; + } + } +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function truncate(s, n) { + if (typeof s === 'string') { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} +function inspect(something) { + if (functionsHaveNames || !util.isFunction(something)) { + return util.inspect(something); + } + var rawname = getName(something); + var name = rawname ? ': ' + rawname : ''; + return '[Function' + name + ']'; +} +function getMessage(self) { + return truncate(inspect(self.actual), 128) + ' ' + + self.operator + ' ' + + truncate(inspect(self.expected), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +assert.deepStrictEqual = function deepStrictEqual(actual, expected, message) { + if (!_deepEqual(actual, expected, true)) { + fail(actual, expected, message, 'deepStrictEqual', assert.deepStrictEqual); + } +}; + +function _deepEqual(actual, expected, strict, memos) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + } else if (isBuffer(actual) && isBuffer(expected)) { + return compare(actual, expected) === 0; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if ((actual === null || typeof actual !== 'object') && + (expected === null || typeof expected !== 'object')) { + return strict ? actual === expected : actual == expected; + + // If both values are instances of typed arrays, wrap their underlying + // ArrayBuffers in a Buffer each to increase performance + // This optimization requires the arrays to have the same type as checked by + // Object.prototype.toString (aka pToString). Never perform binary + // comparisons for Float*Arrays, though, since e.g. +0 === -0 but their + // bit patterns are not identical. + } else if (isView(actual) && isView(expected) && + pToString(actual) === pToString(expected) && + !(actual instanceof Float32Array || + actual instanceof Float64Array)) { + return compare(new Uint8Array(actual.buffer), + new Uint8Array(expected.buffer)) === 0; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else if (isBuffer(actual) !== isBuffer(expected)) { + return false; + } else { + memos = memos || {actual: [], expected: []}; + + var actualIndex = memos.actual.indexOf(actual); + if (actualIndex !== -1) { + if (actualIndex === memos.expected.indexOf(expected)) { + return true; + } + } + + memos.actual.push(actual); + memos.expected.push(expected); + + return objEquiv(actual, expected, strict, memos); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b, strict, actualVisitedObjects) { + if (a === null || a === undefined || b === null || b === undefined) + return false; + // if one is a primitive, the other must be same + if (util.isPrimitive(a) || util.isPrimitive(b)) + return a === b; + if (strict && Object.getPrototypeOf(a) !== Object.getPrototypeOf(b)) + return false; + var aIsArgs = isArguments(a); + var bIsArgs = isArguments(b); + if ((aIsArgs && !bIsArgs) || (!aIsArgs && bIsArgs)) + return false; + if (aIsArgs) { + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b, strict); + } + var ka = objectKeys(a); + var kb = objectKeys(b); + var key, i; + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length !== kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] !== kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key], strict, actualVisitedObjects)) + return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected, false)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +assert.notDeepStrictEqual = notDeepStrictEqual; +function notDeepStrictEqual(actual, expected, message) { + if (_deepEqual(actual, expected, true)) { + fail(actual, expected, message, 'notDeepStrictEqual', notDeepStrictEqual); + } +} + + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } + + try { + if (actual instanceof expected) { + return true; + } + } catch (e) { + // Ignore. The instanceof check doesn't work for arrow functions. + } + + if (Error.isPrototypeOf(expected)) { + return false; + } + + return expected.call({}, actual) === true; +} + +function _tryBlock(block) { + var error; + try { + block(); + } catch (e) { + error = e; + } + return error; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (typeof block !== 'function') { + throw new TypeError('"block" argument must be a function'); + } + + if (typeof expected === 'string') { + message = expected; + expected = null; + } + + actual = _tryBlock(block); + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + var userProvidedMessage = typeof message === 'string'; + var isUnwantedException = !shouldThrow && util.isError(actual); + var isUnexpectedException = !shouldThrow && actual && !expected; + + if ((isUnwantedException && + userProvidedMessage && + expectedException(actual, expected)) || + isUnexpectedException) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws(true, block, error, message); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/error, /*optional*/message) { + _throws(false, block, error, message); +}; + +assert.ifError = function(err) { if (err) throw err; }; + +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + if (hasOwn.call(obj, key)) keys.push(key); + } + return keys; +}; + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"util/":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/util/util.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/base-x/index.js":[function(require,module,exports){ +// base-x encoding +// Forked from https://github.com/cryptocoinjs/bs58 +// Originally written by Mike Hearn for BitcoinJ +// Copyright (c) 2011 Google Inc +// Ported to JavaScript by Stefan Thomas +// Merged Buffer refactorings from base58-native by Stephen Pair +// Copyright (c) 2013 BitPay Inc + +module.exports = function base (ALPHABET) { + var ALPHABET_MAP = {} + var BASE = ALPHABET.length + var LEADER = ALPHABET.charAt(0) + + // pre-compute lookup table + for (var i = 0; i < ALPHABET.length; i++) { + ALPHABET_MAP[ALPHABET.charAt(i)] = i + } + + function encode (source) { + if (source.length === 0) return '' + + var digits = [0] + for (var i = 0; i < source.length; ++i) { + for (var j = 0, carry = source[i]; j < digits.length; ++j) { + carry += digits[j] << 8 + digits[j] = carry % BASE + carry = (carry / BASE) | 0 + } + + while (carry > 0) { + digits.push(carry % BASE) + carry = (carry / BASE) | 0 + } + } + + var string = '' + + // deal with leading zeros + for (var k = 0; source[k] === 0 && k < source.length - 1; ++k) string += ALPHABET[0] + // convert digits to a string + for (var q = digits.length - 1; q >= 0; --q) string += ALPHABET[digits[q]] + + return string + } + + function decodeUnsafe (string) { + if (string.length === 0) return [] + + var bytes = [0] + for (var i = 0; i < string.length; i++) { + var value = ALPHABET_MAP[string[i]] + if (value === undefined) return + + for (var j = 0, carry = value; j < bytes.length; ++j) { + carry += bytes[j] * BASE + bytes[j] = carry & 0xff + carry >>= 8 + } + + while (carry > 0) { + bytes.push(carry & 0xff) + carry >>= 8 + } + } + + // deal with leading zeros + for (var k = 0; string[k] === LEADER && k < string.length - 1; ++k) { + bytes.push(0) + } + + return bytes.reverse() + } + + function decode (string) { + var array = decodeUnsafe(string) + if (array) return array + + throw new Error('Non-base' + BASE + ' character') + } + + return { + encode: encode, + decodeUnsafe: decodeUnsafe, + decode: decode + } +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/base64-js/index.js":[function(require,module,exports){ +'use strict' + +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray + +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} + +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 + +function getLens (b64) { + var len = b64.length + + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } + + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len + + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) + + return [validLen, placeHoldersLen] +} + +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} + +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) + + var curByte = 0 + + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen + + for (var i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } + + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } + + return arr +} + +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} + +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} + +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 + + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } + + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) + } + + return parts.join('') +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/bigi.js":[function(require,module,exports){ +// (public) Constructor +function BigInteger(a, b, c) { + if (!(this instanceof BigInteger)) + return new BigInteger(a, b, c) + + if (a != null) { + if ("number" == typeof a) this.fromNumber(a, b, c) + else if (b == null && "string" != typeof a) this.fromString(a, 256) + else this.fromString(a, b) + } +} + +var proto = BigInteger.prototype + +// duck-typed isBigInteger +proto.__bigi = require('../package.json').version +BigInteger.isBigInteger = function (obj, check_ver) { + return obj && obj.__bigi && (!check_ver || obj.__bigi === proto.__bigi) +} + +// Bits per digit +var dbits + +// am: Compute w_j += (x*this_i), propagate carries, +// c is initial carry, returns final carry. +// c < 3*dvalue, x < 2*dvalue, this_i < dvalue +// We need to select the fastest one that works in this environment. + +// am1: use a single mult and divide to get the high bits, +// max digit bits should be 26 because +// max internal value = 2*dvalue^2-2*dvalue (< 2^53) +function am1(i, x, w, j, c, n) { + while (--n >= 0) { + var v = x * this[i++] + w[j] + c + c = Math.floor(v / 0x4000000) + w[j++] = v & 0x3ffffff + } + return c +} +// am2 avoids a big mult-and-extract completely. +// Max digit bits should be <= 30 because we do bitwise ops +// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31) +function am2(i, x, w, j, c, n) { + var xl = x & 0x7fff, + xh = x >> 15 + while (--n >= 0) { + var l = this[i] & 0x7fff + var h = this[i++] >> 15 + var m = xh * l + h * xl + l = xl * l + ((m & 0x7fff) << 15) + w[j] + (c & 0x3fffffff) + c = (l >>> 30) + (m >>> 15) + xh * h + (c >>> 30) + w[j++] = l & 0x3fffffff + } + return c +} +// Alternately, set max digit bits to 28 since some +// browsers slow down when dealing with 32-bit numbers. +function am3(i, x, w, j, c, n) { + var xl = x & 0x3fff, + xh = x >> 14 + while (--n >= 0) { + var l = this[i] & 0x3fff + var h = this[i++] >> 14 + var m = xh * l + h * xl + l = xl * l + ((m & 0x3fff) << 14) + w[j] + c + c = (l >> 28) + (m >> 14) + xh * h + w[j++] = l & 0xfffffff + } + return c +} + +// wtf? +BigInteger.prototype.am = am1 +dbits = 26 + +BigInteger.prototype.DB = dbits +BigInteger.prototype.DM = ((1 << dbits) - 1) +var DV = BigInteger.prototype.DV = (1 << dbits) + +var BI_FP = 52 +BigInteger.prototype.FV = Math.pow(2, BI_FP) +BigInteger.prototype.F1 = BI_FP - dbits +BigInteger.prototype.F2 = 2 * dbits - BI_FP + +// Digit conversions +var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz" +var BI_RC = new Array() +var rr, vv +rr = "0".charCodeAt(0) +for (vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv +rr = "a".charCodeAt(0) +for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv +rr = "A".charCodeAt(0) +for (vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv + +function int2char(n) { + return BI_RM.charAt(n) +} + +function intAt(s, i) { + var c = BI_RC[s.charCodeAt(i)] + return (c == null) ? -1 : c +} + +// (protected) copy this to r +function bnpCopyTo(r) { + for (var i = this.t - 1; i >= 0; --i) r[i] = this[i] + r.t = this.t + r.s = this.s +} + +// (protected) set from integer value x, -DV <= x < DV +function bnpFromInt(x) { + this.t = 1 + this.s = (x < 0) ? -1 : 0 + if (x > 0) this[0] = x + else if (x < -1) this[0] = x + DV + else this.t = 0 +} + +// return bigint initialized to value +function nbv(i) { + var r = new BigInteger() + r.fromInt(i) + return r +} + +// (protected) set from string and radix +function bnpFromString(s, b) { + var self = this + + var k + if (b == 16) k = 4 + else if (b == 8) k = 3 + else if (b == 256) k = 8; // byte array + else if (b == 2) k = 1 + else if (b == 32) k = 5 + else if (b == 4) k = 2 + else { + self.fromRadix(s, b) + return + } + self.t = 0 + self.s = 0 + var i = s.length, + mi = false, + sh = 0 + while (--i >= 0) { + var x = (k == 8) ? s[i] & 0xff : intAt(s, i) + if (x < 0) { + if (s.charAt(i) == "-") mi = true + continue + } + mi = false + if (sh == 0) + self[self.t++] = x + else if (sh + k > self.DB) { + self[self.t - 1] |= (x & ((1 << (self.DB - sh)) - 1)) << sh + self[self.t++] = (x >> (self.DB - sh)) + } else + self[self.t - 1] |= x << sh + sh += k + if (sh >= self.DB) sh -= self.DB + } + if (k == 8 && (s[0] & 0x80) != 0) { + self.s = -1 + if (sh > 0) self[self.t - 1] |= ((1 << (self.DB - sh)) - 1) << sh + } + self.clamp() + if (mi) BigInteger.ZERO.subTo(self, self) +} + +// (protected) clamp off excess high words +function bnpClamp() { + var c = this.s & this.DM + while (this.t > 0 && this[this.t - 1] == c)--this.t +} + +// (public) return string representation in given radix +function bnToString(b) { + var self = this + if (self.s < 0) return "-" + self.negate() + .toString(b) + var k + if (b == 16) k = 4 + else if (b == 8) k = 3 + else if (b == 2) k = 1 + else if (b == 32) k = 5 + else if (b == 4) k = 2 + else return self.toRadix(b) + var km = (1 << k) - 1, + d, m = false, + r = "", + i = self.t + var p = self.DB - (i * self.DB) % k + if (i-- > 0) { + if (p < self.DB && (d = self[i] >> p) > 0) { + m = true + r = int2char(d) + } + while (i >= 0) { + if (p < k) { + d = (self[i] & ((1 << p) - 1)) << (k - p) + d |= self[--i] >> (p += self.DB - k) + } else { + d = (self[i] >> (p -= k)) & km + if (p <= 0) { + p += self.DB + --i + } + } + if (d > 0) m = true + if (m) r += int2char(d) + } + } + return m ? r : "0" +} + +// (public) -this +function bnNegate() { + var r = new BigInteger() + BigInteger.ZERO.subTo(this, r) + return r +} + +// (public) |this| +function bnAbs() { + return (this.s < 0) ? this.negate() : this +} + +// (public) return + if this > a, - if this < a, 0 if equal +function bnCompareTo(a) { + var r = this.s - a.s + if (r != 0) return r + var i = this.t + r = i - a.t + if (r != 0) return (this.s < 0) ? -r : r + while (--i >= 0) + if ((r = this[i] - a[i]) != 0) return r + return 0 +} + +// returns bit length of the integer x +function nbits(x) { + var r = 1, + t + if ((t = x >>> 16) != 0) { + x = t + r += 16 + } + if ((t = x >> 8) != 0) { + x = t + r += 8 + } + if ((t = x >> 4) != 0) { + x = t + r += 4 + } + if ((t = x >> 2) != 0) { + x = t + r += 2 + } + if ((t = x >> 1) != 0) { + x = t + r += 1 + } + return r +} + +// (public) return the number of bits in "this" +function bnBitLength() { + if (this.t <= 0) return 0 + return this.DB * (this.t - 1) + nbits(this[this.t - 1] ^ (this.s & this.DM)) +} + +// (public) return the number of bytes in "this" +function bnByteLength() { + return this.bitLength() >> 3 +} + +// (protected) r = this << n*DB +function bnpDLShiftTo(n, r) { + var i + for (i = this.t - 1; i >= 0; --i) r[i + n] = this[i] + for (i = n - 1; i >= 0; --i) r[i] = 0 + r.t = this.t + n + r.s = this.s +} + +// (protected) r = this >> n*DB +function bnpDRShiftTo(n, r) { + for (var i = n; i < this.t; ++i) r[i - n] = this[i] + r.t = Math.max(this.t - n, 0) + r.s = this.s +} + +// (protected) r = this << n +function bnpLShiftTo(n, r) { + var self = this + var bs = n % self.DB + var cbs = self.DB - bs + var bm = (1 << cbs) - 1 + var ds = Math.floor(n / self.DB), + c = (self.s << bs) & self.DM, + i + for (i = self.t - 1; i >= 0; --i) { + r[i + ds + 1] = (self[i] >> cbs) | c + c = (self[i] & bm) << bs + } + for (i = ds - 1; i >= 0; --i) r[i] = 0 + r[ds] = c + r.t = self.t + ds + 1 + r.s = self.s + r.clamp() +} + +// (protected) r = this >> n +function bnpRShiftTo(n, r) { + var self = this + r.s = self.s + var ds = Math.floor(n / self.DB) + if (ds >= self.t) { + r.t = 0 + return + } + var bs = n % self.DB + var cbs = self.DB - bs + var bm = (1 << bs) - 1 + r[0] = self[ds] >> bs + for (var i = ds + 1; i < self.t; ++i) { + r[i - ds - 1] |= (self[i] & bm) << cbs + r[i - ds] = self[i] >> bs + } + if (bs > 0) r[self.t - ds - 1] |= (self.s & bm) << cbs + r.t = self.t - ds + r.clamp() +} + +// (protected) r = this - a +function bnpSubTo(a, r) { + var self = this + var i = 0, + c = 0, + m = Math.min(a.t, self.t) + while (i < m) { + c += self[i] - a[i] + r[i++] = c & self.DM + c >>= self.DB + } + if (a.t < self.t) { + c -= a.s + while (i < self.t) { + c += self[i] + r[i++] = c & self.DM + c >>= self.DB + } + c += self.s + } else { + c += self.s + while (i < a.t) { + c -= a[i] + r[i++] = c & self.DM + c >>= self.DB + } + c -= a.s + } + r.s = (c < 0) ? -1 : 0 + if (c < -1) r[i++] = self.DV + c + else if (c > 0) r[i++] = c + r.t = i + r.clamp() +} + +// (protected) r = this * a, r != this,a (HAC 14.12) +// "this" should be the larger one if appropriate. +function bnpMultiplyTo(a, r) { + var x = this.abs(), + y = a.abs() + var i = x.t + r.t = i + y.t + while (--i >= 0) r[i] = 0 + for (i = 0; i < y.t; ++i) r[i + x.t] = x.am(0, y[i], r, i, 0, x.t) + r.s = 0 + r.clamp() + if (this.s != a.s) BigInteger.ZERO.subTo(r, r) +} + +// (protected) r = this^2, r != this (HAC 14.16) +function bnpSquareTo(r) { + var x = this.abs() + var i = r.t = 2 * x.t + while (--i >= 0) r[i] = 0 + for (i = 0; i < x.t - 1; ++i) { + var c = x.am(i, x[i], r, 2 * i, 0, 1) + if ((r[i + x.t] += x.am(i + 1, 2 * x[i], r, 2 * i + 1, c, x.t - i - 1)) >= x.DV) { + r[i + x.t] -= x.DV + r[i + x.t + 1] = 1 + } + } + if (r.t > 0) r[r.t - 1] += x.am(i, x[i], r, 2 * i, 0, 1) + r.s = 0 + r.clamp() +} + +// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20) +// r != q, this != m. q or r may be null. +function bnpDivRemTo(m, q, r) { + var self = this + var pm = m.abs() + if (pm.t <= 0) return + var pt = self.abs() + if (pt.t < pm.t) { + if (q != null) q.fromInt(0) + if (r != null) self.copyTo(r) + return + } + if (r == null) r = new BigInteger() + var y = new BigInteger(), + ts = self.s, + ms = m.s + var nsh = self.DB - nbits(pm[pm.t - 1]); // normalize modulus + if (nsh > 0) { + pm.lShiftTo(nsh, y) + pt.lShiftTo(nsh, r) + } else { + pm.copyTo(y) + pt.copyTo(r) + } + var ys = y.t + var y0 = y[ys - 1] + if (y0 == 0) return + var yt = y0 * (1 << self.F1) + ((ys > 1) ? y[ys - 2] >> self.F2 : 0) + var d1 = self.FV / yt, + d2 = (1 << self.F1) / yt, + e = 1 << self.F2 + var i = r.t, + j = i - ys, + t = (q == null) ? new BigInteger() : q + y.dlShiftTo(j, t) + if (r.compareTo(t) >= 0) { + r[r.t++] = 1 + r.subTo(t, r) + } + BigInteger.ONE.dlShiftTo(ys, t) + t.subTo(y, y); // "negative" y so we can replace sub with am later + while (y.t < ys) y[y.t++] = 0 + while (--j >= 0) { + // Estimate quotient digit + var qd = (r[--i] == y0) ? self.DM : Math.floor(r[i] * d1 + (r[i - 1] + e) * d2) + if ((r[i] += y.am(0, qd, r, j, 0, ys)) < qd) { // Try it out + y.dlShiftTo(j, t) + r.subTo(t, r) + while (r[i] < --qd) r.subTo(t, r) + } + } + if (q != null) { + r.drShiftTo(ys, q) + if (ts != ms) BigInteger.ZERO.subTo(q, q) + } + r.t = ys + r.clamp() + if (nsh > 0) r.rShiftTo(nsh, r); // Denormalize remainder + if (ts < 0) BigInteger.ZERO.subTo(r, r) +} + +// (public) this mod a +function bnMod(a) { + var r = new BigInteger() + this.abs() + .divRemTo(a, null, r) + if (this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r, r) + return r +} + +// Modular reduction using "classic" algorithm +function Classic(m) { + this.m = m +} + +function cConvert(x) { + if (x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m) + else return x +} + +function cRevert(x) { + return x +} + +function cReduce(x) { + x.divRemTo(this.m, null, x) +} + +function cMulTo(x, y, r) { + x.multiplyTo(y, r) + this.reduce(r) +} + +function cSqrTo(x, r) { + x.squareTo(r) + this.reduce(r) +} + +Classic.prototype.convert = cConvert +Classic.prototype.revert = cRevert +Classic.prototype.reduce = cReduce +Classic.prototype.mulTo = cMulTo +Classic.prototype.sqrTo = cSqrTo + +// (protected) return "-1/this % 2^DB"; useful for Mont. reduction +// justification: +// xy == 1 (mod m) +// xy = 1+km +// xy(2-xy) = (1+km)(1-km) +// x[y(2-xy)] = 1-k^2m^2 +// x[y(2-xy)] == 1 (mod m^2) +// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2 +// should reduce x and y(2-xy) by m^2 at each step to keep size bounded. +// JS multiply "overflows" differently from C/C++, so care is needed here. +function bnpInvDigit() { + if (this.t < 1) return 0 + var x = this[0] + if ((x & 1) == 0) return 0 + var y = x & 3; // y == 1/x mod 2^2 + y = (y * (2 - (x & 0xf) * y)) & 0xf; // y == 1/x mod 2^4 + y = (y * (2 - (x & 0xff) * y)) & 0xff; // y == 1/x mod 2^8 + y = (y * (2 - (((x & 0xffff) * y) & 0xffff))) & 0xffff; // y == 1/x mod 2^16 + // last step - calculate inverse mod DV directly + // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints + y = (y * (2 - x * y % this.DV)) % this.DV; // y == 1/x mod 2^dbits + // we really want the negative inverse, and -DV < y < DV + return (y > 0) ? this.DV - y : -y +} + +// Montgomery reduction +function Montgomery(m) { + this.m = m + this.mp = m.invDigit() + this.mpl = this.mp & 0x7fff + this.mph = this.mp >> 15 + this.um = (1 << (m.DB - 15)) - 1 + this.mt2 = 2 * m.t +} + +// xR mod m +function montConvert(x) { + var r = new BigInteger() + x.abs() + .dlShiftTo(this.m.t, r) + r.divRemTo(this.m, null, r) + if (x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r, r) + return r +} + +// x/R mod m +function montRevert(x) { + var r = new BigInteger() + x.copyTo(r) + this.reduce(r) + return r +} + +// x = x/R mod m (HAC 14.32) +function montReduce(x) { + while (x.t <= this.mt2) // pad x so am has enough room later + x[x.t++] = 0 + for (var i = 0; i < this.m.t; ++i) { + // faster way of calculating u0 = x[i]*mp mod DV + var j = x[i] & 0x7fff + var u0 = (j * this.mpl + (((j * this.mph + (x[i] >> 15) * this.mpl) & this.um) << 15)) & x.DM + // use am to combine the multiply-shift-add into one call + j = i + this.m.t + x[j] += this.m.am(0, u0, x, i, 0, this.m.t) + // propagate carry + while (x[j] >= x.DV) { + x[j] -= x.DV + x[++j]++ + } + } + x.clamp() + x.drShiftTo(this.m.t, x) + if (x.compareTo(this.m) >= 0) x.subTo(this.m, x) +} + +// r = "x^2/R mod m"; x != r +function montSqrTo(x, r) { + x.squareTo(r) + this.reduce(r) +} + +// r = "xy/R mod m"; x,y != r +function montMulTo(x, y, r) { + x.multiplyTo(y, r) + this.reduce(r) +} + +Montgomery.prototype.convert = montConvert +Montgomery.prototype.revert = montRevert +Montgomery.prototype.reduce = montReduce +Montgomery.prototype.mulTo = montMulTo +Montgomery.prototype.sqrTo = montSqrTo + +// (protected) true iff this is even +function bnpIsEven() { + return ((this.t > 0) ? (this[0] & 1) : this.s) == 0 +} + +// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79) +function bnpExp(e, z) { + if (e > 0xffffffff || e < 1) return BigInteger.ONE + var r = new BigInteger(), + r2 = new BigInteger(), + g = z.convert(this), + i = nbits(e) - 1 + g.copyTo(r) + while (--i >= 0) { + z.sqrTo(r, r2) + if ((e & (1 << i)) > 0) z.mulTo(r2, g, r) + else { + var t = r + r = r2 + r2 = t + } + } + return z.revert(r) +} + +// (public) this^e % m, 0 <= e < 2^32 +function bnModPowInt(e, m) { + var z + if (e < 256 || m.isEven()) z = new Classic(m) + else z = new Montgomery(m) + return this.exp(e, z) +} + +// protected +proto.copyTo = bnpCopyTo +proto.fromInt = bnpFromInt +proto.fromString = bnpFromString +proto.clamp = bnpClamp +proto.dlShiftTo = bnpDLShiftTo +proto.drShiftTo = bnpDRShiftTo +proto.lShiftTo = bnpLShiftTo +proto.rShiftTo = bnpRShiftTo +proto.subTo = bnpSubTo +proto.multiplyTo = bnpMultiplyTo +proto.squareTo = bnpSquareTo +proto.divRemTo = bnpDivRemTo +proto.invDigit = bnpInvDigit +proto.isEven = bnpIsEven +proto.exp = bnpExp + +// public +proto.toString = bnToString +proto.negate = bnNegate +proto.abs = bnAbs +proto.compareTo = bnCompareTo +proto.bitLength = bnBitLength +proto.byteLength = bnByteLength +proto.mod = bnMod +proto.modPowInt = bnModPowInt + +// (public) +function bnClone() { + var r = new BigInteger() + this.copyTo(r) + return r +} + +// (public) return value as integer +function bnIntValue() { + if (this.s < 0) { + if (this.t == 1) return this[0] - this.DV + else if (this.t == 0) return -1 + } else if (this.t == 1) return this[0] + else if (this.t == 0) return 0 + // assumes 16 < DB < 32 + return ((this[1] & ((1 << (32 - this.DB)) - 1)) << this.DB) | this[0] +} + +// (public) return value as byte +function bnByteValue() { + return (this.t == 0) ? this.s : (this[0] << 24) >> 24 +} + +// (public) return value as short (assumes DB>=16) +function bnShortValue() { + return (this.t == 0) ? this.s : (this[0] << 16) >> 16 +} + +// (protected) return x s.t. r^x < DV +function bnpChunkSize(r) { + return Math.floor(Math.LN2 * this.DB / Math.log(r)) +} + +// (public) 0 if this == 0, 1 if this > 0 +function bnSigNum() { + if (this.s < 0) return -1 + else if (this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0 + else return 1 +} + +// (protected) convert to radix string +function bnpToRadix(b) { + if (b == null) b = 10 + if (this.signum() == 0 || b < 2 || b > 36) return "0" + var cs = this.chunkSize(b) + var a = Math.pow(b, cs) + var d = nbv(a), + y = new BigInteger(), + z = new BigInteger(), + r = "" + this.divRemTo(d, y, z) + while (y.signum() > 0) { + r = (a + z.intValue()) + .toString(b) + .substr(1) + r + y.divRemTo(d, y, z) + } + return z.intValue() + .toString(b) + r +} + +// (protected) convert from radix string +function bnpFromRadix(s, b) { + var self = this + self.fromInt(0) + if (b == null) b = 10 + var cs = self.chunkSize(b) + var d = Math.pow(b, cs), + mi = false, + j = 0, + w = 0 + for (var i = 0; i < s.length; ++i) { + var x = intAt(s, i) + if (x < 0) { + if (s.charAt(i) == "-" && self.signum() == 0) mi = true + continue + } + w = b * w + x + if (++j >= cs) { + self.dMultiply(d) + self.dAddOffset(w, 0) + j = 0 + w = 0 + } + } + if (j > 0) { + self.dMultiply(Math.pow(b, j)) + self.dAddOffset(w, 0) + } + if (mi) BigInteger.ZERO.subTo(self, self) +} + +// (protected) alternate constructor +function bnpFromNumber(a, b, c) { + var self = this + if ("number" == typeof b) { + // new BigInteger(int,int,RNG) + if (a < 2) self.fromInt(1) + else { + self.fromNumber(a, c) + if (!self.testBit(a - 1)) // force MSB set + self.bitwiseTo(BigInteger.ONE.shiftLeft(a - 1), op_or, self) + if (self.isEven()) self.dAddOffset(1, 0); // force odd + while (!self.isProbablePrime(b)) { + self.dAddOffset(2, 0) + if (self.bitLength() > a) self.subTo(BigInteger.ONE.shiftLeft(a - 1), self) + } + } + } else { + // new BigInteger(int,RNG) + var x = new Array(), + t = a & 7 + x.length = (a >> 3) + 1 + b.nextBytes(x) + if (t > 0) x[0] &= ((1 << t) - 1) + else x[0] = 0 + self.fromString(x, 256) + } +} + +// (public) convert to bigendian byte array +function bnToByteArray() { + var self = this + var i = self.t, + r = new Array() + r[0] = self.s + var p = self.DB - (i * self.DB) % 8, + d, k = 0 + if (i-- > 0) { + if (p < self.DB && (d = self[i] >> p) != (self.s & self.DM) >> p) + r[k++] = d | (self.s << (self.DB - p)) + while (i >= 0) { + if (p < 8) { + d = (self[i] & ((1 << p) - 1)) << (8 - p) + d |= self[--i] >> (p += self.DB - 8) + } else { + d = (self[i] >> (p -= 8)) & 0xff + if (p <= 0) { + p += self.DB + --i + } + } + if ((d & 0x80) != 0) d |= -256 + if (k === 0 && (self.s & 0x80) != (d & 0x80))++k + if (k > 0 || d != self.s) r[k++] = d + } + } + return r +} + +function bnEquals(a) { + return (this.compareTo(a) == 0) +} + +function bnMin(a) { + return (this.compareTo(a) < 0) ? this : a +} + +function bnMax(a) { + return (this.compareTo(a) > 0) ? this : a +} + +// (protected) r = this op a (bitwise) +function bnpBitwiseTo(a, op, r) { + var self = this + var i, f, m = Math.min(a.t, self.t) + for (i = 0; i < m; ++i) r[i] = op(self[i], a[i]) + if (a.t < self.t) { + f = a.s & self.DM + for (i = m; i < self.t; ++i) r[i] = op(self[i], f) + r.t = self.t + } else { + f = self.s & self.DM + for (i = m; i < a.t; ++i) r[i] = op(f, a[i]) + r.t = a.t + } + r.s = op(self.s, a.s) + r.clamp() +} + +// (public) this & a +function op_and(x, y) { + return x & y +} + +function bnAnd(a) { + var r = new BigInteger() + this.bitwiseTo(a, op_and, r) + return r +} + +// (public) this | a +function op_or(x, y) { + return x | y +} + +function bnOr(a) { + var r = new BigInteger() + this.bitwiseTo(a, op_or, r) + return r +} + +// (public) this ^ a +function op_xor(x, y) { + return x ^ y +} + +function bnXor(a) { + var r = new BigInteger() + this.bitwiseTo(a, op_xor, r) + return r +} + +// (public) this & ~a +function op_andnot(x, y) { + return x & ~y +} + +function bnAndNot(a) { + var r = new BigInteger() + this.bitwiseTo(a, op_andnot, r) + return r +} + +// (public) ~this +function bnNot() { + var r = new BigInteger() + for (var i = 0; i < this.t; ++i) r[i] = this.DM & ~this[i] + r.t = this.t + r.s = ~this.s + return r +} + +// (public) this << n +function bnShiftLeft(n) { + var r = new BigInteger() + if (n < 0) this.rShiftTo(-n, r) + else this.lShiftTo(n, r) + return r +} + +// (public) this >> n +function bnShiftRight(n) { + var r = new BigInteger() + if (n < 0) this.lShiftTo(-n, r) + else this.rShiftTo(n, r) + return r +} + +// return index of lowest 1-bit in x, x < 2^31 +function lbit(x) { + if (x == 0) return -1 + var r = 0 + if ((x & 0xffff) == 0) { + x >>= 16 + r += 16 + } + if ((x & 0xff) == 0) { + x >>= 8 + r += 8 + } + if ((x & 0xf) == 0) { + x >>= 4 + r += 4 + } + if ((x & 3) == 0) { + x >>= 2 + r += 2 + } + if ((x & 1) == 0)++r + return r +} + +// (public) returns index of lowest 1-bit (or -1 if none) +function bnGetLowestSetBit() { + for (var i = 0; i < this.t; ++i) + if (this[i] != 0) return i * this.DB + lbit(this[i]) + if (this.s < 0) return this.t * this.DB + return -1 +} + +// return number of 1 bits in x +function cbit(x) { + var r = 0 + while (x != 0) { + x &= x - 1 + ++r + } + return r +} + +// (public) return number of set bits +function bnBitCount() { + var r = 0, + x = this.s & this.DM + for (var i = 0; i < this.t; ++i) r += cbit(this[i] ^ x) + return r +} + +// (public) true iff nth bit is set +function bnTestBit(n) { + var j = Math.floor(n / this.DB) + if (j >= this.t) return (this.s != 0) + return ((this[j] & (1 << (n % this.DB))) != 0) +} + +// (protected) this op (1<>= self.DB + } + if (a.t < self.t) { + c += a.s + while (i < self.t) { + c += self[i] + r[i++] = c & self.DM + c >>= self.DB + } + c += self.s + } else { + c += self.s + while (i < a.t) { + c += a[i] + r[i++] = c & self.DM + c >>= self.DB + } + c += a.s + } + r.s = (c < 0) ? -1 : 0 + if (c > 0) r[i++] = c + else if (c < -1) r[i++] = self.DV + c + r.t = i + r.clamp() +} + +// (public) this + a +function bnAdd(a) { + var r = new BigInteger() + this.addTo(a, r) + return r +} + +// (public) this - a +function bnSubtract(a) { + var r = new BigInteger() + this.subTo(a, r) + return r +} + +// (public) this * a +function bnMultiply(a) { + var r = new BigInteger() + this.multiplyTo(a, r) + return r +} + +// (public) this^2 +function bnSquare() { + var r = new BigInteger() + this.squareTo(r) + return r +} + +// (public) this / a +function bnDivide(a) { + var r = new BigInteger() + this.divRemTo(a, r, null) + return r +} + +// (public) this % a +function bnRemainder(a) { + var r = new BigInteger() + this.divRemTo(a, null, r) + return r +} + +// (public) [this/a,this%a] +function bnDivideAndRemainder(a) { + var q = new BigInteger(), + r = new BigInteger() + this.divRemTo(a, q, r) + return new Array(q, r) +} + +// (protected) this *= n, this >= 0, 1 < n < DV +function bnpDMultiply(n) { + this[this.t] = this.am(0, n - 1, this, 0, 0, this.t) + ++this.t + this.clamp() +} + +// (protected) this += n << w words, this >= 0 +function bnpDAddOffset(n, w) { + if (n == 0) return + while (this.t <= w) this[this.t++] = 0 + this[w] += n + while (this[w] >= this.DV) { + this[w] -= this.DV + if (++w >= this.t) this[this.t++] = 0 + ++this[w] + } +} + +// A "null" reducer +function NullExp() {} + +function nNop(x) { + return x +} + +function nMulTo(x, y, r) { + x.multiplyTo(y, r) +} + +function nSqrTo(x, r) { + x.squareTo(r) +} + +NullExp.prototype.convert = nNop +NullExp.prototype.revert = nNop +NullExp.prototype.mulTo = nMulTo +NullExp.prototype.sqrTo = nSqrTo + +// (public) this^e +function bnPow(e) { + return this.exp(e, new NullExp()) +} + +// (protected) r = lower n words of "this * a", a.t <= n +// "this" should be the larger one if appropriate. +function bnpMultiplyLowerTo(a, n, r) { + var i = Math.min(this.t + a.t, n) + r.s = 0; // assumes a,this >= 0 + r.t = i + while (i > 0) r[--i] = 0 + var j + for (j = r.t - this.t; i < j; ++i) r[i + this.t] = this.am(0, a[i], r, i, 0, this.t) + for (j = Math.min(a.t, n); i < j; ++i) this.am(0, a[i], r, i, 0, n - i) + r.clamp() +} + +// (protected) r = "this * a" without lower n words, n > 0 +// "this" should be the larger one if appropriate. +function bnpMultiplyUpperTo(a, n, r) { + --n + var i = r.t = this.t + a.t - n + r.s = 0; // assumes a,this >= 0 + while (--i >= 0) r[i] = 0 + for (i = Math.max(n - this.t, 0); i < a.t; ++i) + r[this.t + i - n] = this.am(n - i, a[i], r, 0, 0, this.t + i - n) + r.clamp() + r.drShiftTo(1, r) +} + +// Barrett modular reduction +function Barrett(m) { + // setup Barrett + this.r2 = new BigInteger() + this.q3 = new BigInteger() + BigInteger.ONE.dlShiftTo(2 * m.t, this.r2) + this.mu = this.r2.divide(m) + this.m = m +} + +function barrettConvert(x) { + if (x.s < 0 || x.t > 2 * this.m.t) return x.mod(this.m) + else if (x.compareTo(this.m) < 0) return x + else { + var r = new BigInteger() + x.copyTo(r) + this.reduce(r) + return r + } +} + +function barrettRevert(x) { + return x +} + +// x = x mod m (HAC 14.42) +function barrettReduce(x) { + var self = this + x.drShiftTo(self.m.t - 1, self.r2) + if (x.t > self.m.t + 1) { + x.t = self.m.t + 1 + x.clamp() + } + self.mu.multiplyUpperTo(self.r2, self.m.t + 1, self.q3) + self.m.multiplyLowerTo(self.q3, self.m.t + 1, self.r2) + while (x.compareTo(self.r2) < 0) x.dAddOffset(1, self.m.t + 1) + x.subTo(self.r2, x) + while (x.compareTo(self.m) >= 0) x.subTo(self.m, x) +} + +// r = x^2 mod m; x != r +function barrettSqrTo(x, r) { + x.squareTo(r) + this.reduce(r) +} + +// r = x*y mod m; x,y != r +function barrettMulTo(x, y, r) { + x.multiplyTo(y, r) + this.reduce(r) +} + +Barrett.prototype.convert = barrettConvert +Barrett.prototype.revert = barrettRevert +Barrett.prototype.reduce = barrettReduce +Barrett.prototype.mulTo = barrettMulTo +Barrett.prototype.sqrTo = barrettSqrTo + +// (public) this^e % m (HAC 14.85) +function bnModPow(e, m) { + var i = e.bitLength(), + k, r = nbv(1), + z + if (i <= 0) return r + else if (i < 18) k = 1 + else if (i < 48) k = 3 + else if (i < 144) k = 4 + else if (i < 768) k = 5 + else k = 6 + if (i < 8) + z = new Classic(m) + else if (m.isEven()) + z = new Barrett(m) + else + z = new Montgomery(m) + + // precomputation + var g = new Array(), + n = 3, + k1 = k - 1, + km = (1 << k) - 1 + g[1] = z.convert(this) + if (k > 1) { + var g2 = new BigInteger() + z.sqrTo(g[1], g2) + while (n <= km) { + g[n] = new BigInteger() + z.mulTo(g2, g[n - 2], g[n]) + n += 2 + } + } + + var j = e.t - 1, + w, is1 = true, + r2 = new BigInteger(), + t + i = nbits(e[j]) - 1 + while (j >= 0) { + if (i >= k1) w = (e[j] >> (i - k1)) & km + else { + w = (e[j] & ((1 << (i + 1)) - 1)) << (k1 - i) + if (j > 0) w |= e[j - 1] >> (this.DB + i - k1) + } + + n = k + while ((w & 1) == 0) { + w >>= 1 + --n + } + if ((i -= n) < 0) { + i += this.DB + --j + } + if (is1) { // ret == 1, don't bother squaring or multiplying it + g[w].copyTo(r) + is1 = false + } else { + while (n > 1) { + z.sqrTo(r, r2) + z.sqrTo(r2, r) + n -= 2 + } + if (n > 0) z.sqrTo(r, r2) + else { + t = r + r = r2 + r2 = t + } + z.mulTo(r2, g[w], r) + } + + while (j >= 0 && (e[j] & (1 << i)) == 0) { + z.sqrTo(r, r2) + t = r + r = r2 + r2 = t + if (--i < 0) { + i = this.DB - 1 + --j + } + } + } + return z.revert(r) +} + +// (public) gcd(this,a) (HAC 14.54) +function bnGCD(a) { + var x = (this.s < 0) ? this.negate() : this.clone() + var y = (a.s < 0) ? a.negate() : a.clone() + if (x.compareTo(y) < 0) { + var t = x + x = y + y = t + } + var i = x.getLowestSetBit(), + g = y.getLowestSetBit() + if (g < 0) return x + if (i < g) g = i + if (g > 0) { + x.rShiftTo(g, x) + y.rShiftTo(g, y) + } + while (x.signum() > 0) { + if ((i = x.getLowestSetBit()) > 0) x.rShiftTo(i, x) + if ((i = y.getLowestSetBit()) > 0) y.rShiftTo(i, y) + if (x.compareTo(y) >= 0) { + x.subTo(y, x) + x.rShiftTo(1, x) + } else { + y.subTo(x, y) + y.rShiftTo(1, y) + } + } + if (g > 0) y.lShiftTo(g, y) + return y +} + +// (protected) this % n, n < 2^26 +function bnpModInt(n) { + if (n <= 0) return 0 + var d = this.DV % n, + r = (this.s < 0) ? n - 1 : 0 + if (this.t > 0) + if (d == 0) r = this[0] % n + else + for (var i = this.t - 1; i >= 0; --i) r = (d * r + this[i]) % n + return r +} + +// (public) 1/this % m (HAC 14.61) +function bnModInverse(m) { + var ac = m.isEven() + if (this.signum() === 0) throw new Error('division by zero') + if ((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO + var u = m.clone(), + v = this.clone() + var a = nbv(1), + b = nbv(0), + c = nbv(0), + d = nbv(1) + while (u.signum() != 0) { + while (u.isEven()) { + u.rShiftTo(1, u) + if (ac) { + if (!a.isEven() || !b.isEven()) { + a.addTo(this, a) + b.subTo(m, b) + } + a.rShiftTo(1, a) + } else if (!b.isEven()) b.subTo(m, b) + b.rShiftTo(1, b) + } + while (v.isEven()) { + v.rShiftTo(1, v) + if (ac) { + if (!c.isEven() || !d.isEven()) { + c.addTo(this, c) + d.subTo(m, d) + } + c.rShiftTo(1, c) + } else if (!d.isEven()) d.subTo(m, d) + d.rShiftTo(1, d) + } + if (u.compareTo(v) >= 0) { + u.subTo(v, u) + if (ac) a.subTo(c, a) + b.subTo(d, b) + } else { + v.subTo(u, v) + if (ac) c.subTo(a, c) + d.subTo(b, d) + } + } + if (v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO + while (d.compareTo(m) >= 0) d.subTo(m, d) + while (d.signum() < 0) d.addTo(m, d) + return d +} + +var lowprimes = [ + 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, + 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, + 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, + 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, + 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, + 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, + 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, + 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, + 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, + 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997 +] + +var lplim = (1 << 26) / lowprimes[lowprimes.length - 1] + +// (public) test primality with certainty >= 1-.5^t +function bnIsProbablePrime(t) { + var i, x = this.abs() + if (x.t == 1 && x[0] <= lowprimes[lowprimes.length - 1]) { + for (i = 0; i < lowprimes.length; ++i) + if (x[0] == lowprimes[i]) return true + return false + } + if (x.isEven()) return false + i = 1 + while (i < lowprimes.length) { + var m = lowprimes[i], + j = i + 1 + while (j < lowprimes.length && m < lplim) m *= lowprimes[j++] + m = x.modInt(m) + while (i < j) if (m % lowprimes[i++] == 0) return false + } + return x.millerRabin(t) +} + +// (protected) true if probably prime (HAC 4.24, Miller-Rabin) +function bnpMillerRabin(t) { + var n1 = this.subtract(BigInteger.ONE) + var k = n1.getLowestSetBit() + if (k <= 0) return false + var r = n1.shiftRight(k) + t = (t + 1) >> 1 + if (t > lowprimes.length) t = lowprimes.length + var a = new BigInteger(null) + var j, bases = [] + for (var i = 0; i < t; ++i) { + for (;;) { + j = lowprimes[Math.floor(Math.random() * lowprimes.length)] + if (bases.indexOf(j) == -1) break + } + bases.push(j) + a.fromInt(j) + var y = a.modPow(r, this) + if (y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) { + var j = 1 + while (j++ < k && y.compareTo(n1) != 0) { + y = y.modPowInt(2, this) + if (y.compareTo(BigInteger.ONE) == 0) return false + } + if (y.compareTo(n1) != 0) return false + } + } + return true +} + +// protected +proto.chunkSize = bnpChunkSize +proto.toRadix = bnpToRadix +proto.fromRadix = bnpFromRadix +proto.fromNumber = bnpFromNumber +proto.bitwiseTo = bnpBitwiseTo +proto.changeBit = bnpChangeBit +proto.addTo = bnpAddTo +proto.dMultiply = bnpDMultiply +proto.dAddOffset = bnpDAddOffset +proto.multiplyLowerTo = bnpMultiplyLowerTo +proto.multiplyUpperTo = bnpMultiplyUpperTo +proto.modInt = bnpModInt +proto.millerRabin = bnpMillerRabin + +// public +proto.clone = bnClone +proto.intValue = bnIntValue +proto.byteValue = bnByteValue +proto.shortValue = bnShortValue +proto.signum = bnSigNum +proto.toByteArray = bnToByteArray +proto.equals = bnEquals +proto.min = bnMin +proto.max = bnMax +proto.and = bnAnd +proto.or = bnOr +proto.xor = bnXor +proto.andNot = bnAndNot +proto.not = bnNot +proto.shiftLeft = bnShiftLeft +proto.shiftRight = bnShiftRight +proto.getLowestSetBit = bnGetLowestSetBit +proto.bitCount = bnBitCount +proto.testBit = bnTestBit +proto.setBit = bnSetBit +proto.clearBit = bnClearBit +proto.flipBit = bnFlipBit +proto.add = bnAdd +proto.subtract = bnSubtract +proto.multiply = bnMultiply +proto.divide = bnDivide +proto.remainder = bnRemainder +proto.divideAndRemainder = bnDivideAndRemainder +proto.modPow = bnModPow +proto.modInverse = bnModInverse +proto.pow = bnPow +proto.gcd = bnGCD +proto.isProbablePrime = bnIsProbablePrime + +// JSBN-specific extension +proto.square = bnSquare + +// constants +BigInteger.ZERO = nbv(0) +BigInteger.ONE = nbv(1) +BigInteger.valueOf = nbv + +module.exports = BigInteger + +},{"../package.json":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/package.json"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/convert.js":[function(require,module,exports){ +(function (Buffer){ +// FIXME: Kind of a weird way to throw exceptions, consider removing +var assert = require('assert') +var BigInteger = require('./bigi') + +/** + * Turns a byte array into a big integer. + * + * This function will interpret a byte array as a big integer in big + * endian notation. + */ +BigInteger.fromByteArrayUnsigned = function(byteArray) { + // BigInteger expects a DER integer conformant byte array + if (byteArray[0] & 0x80) { + return new BigInteger([0].concat(byteArray)) + } + + return new BigInteger(byteArray) +} + +/** + * Returns a byte array representation of the big integer. + * + * This returns the absolute of the contained value in big endian + * form. A value of zero results in an empty array. + */ +BigInteger.prototype.toByteArrayUnsigned = function() { + var byteArray = this.toByteArray() + return byteArray[0] === 0 ? byteArray.slice(1) : byteArray +} + +BigInteger.fromDERInteger = function(byteArray) { + return new BigInteger(byteArray) +} + +/* + * Converts BigInteger to a DER integer representation. + * + * The format for this value uses the most significant bit as a sign + * bit. If the most significant bit is already set and the integer is + * positive, a 0x00 is prepended. + * + * Examples: + * + * 0 => 0x00 + * 1 => 0x01 + * -1 => 0xff + * 127 => 0x7f + * -127 => 0x81 + * 128 => 0x0080 + * -128 => 0x80 + * 255 => 0x00ff + * -255 => 0xff01 + * 16300 => 0x3fac + * -16300 => 0xc054 + * 62300 => 0x00f35c + * -62300 => 0xff0ca4 +*/ +BigInteger.prototype.toDERInteger = BigInteger.prototype.toByteArray + +BigInteger.fromBuffer = function(buffer) { + // BigInteger expects a DER integer conformant byte array + if (buffer[0] & 0x80) { + var byteArray = Array.prototype.slice.call(buffer) + + return new BigInteger([0].concat(byteArray)) + } + + return new BigInteger(buffer) +} + +BigInteger.fromHex = function(hex) { + if (hex === '') return BigInteger.ZERO + + assert.equal(hex, hex.match(/^[A-Fa-f0-9]+/), 'Invalid hex string') + assert.equal(hex.length % 2, 0, 'Incomplete hex') + return new BigInteger(hex, 16) +} + +BigInteger.prototype.toBuffer = function(size) { + var byteArray = this.toByteArrayUnsigned() + var zeros = [] + + var padding = size - byteArray.length + while (zeros.length < padding) zeros.push(0) + + return new Buffer(zeros.concat(byteArray)) +} + +BigInteger.prototype.toHex = function(size) { + return this.toBuffer(size).toString('hex') +} + +}).call(this,require("buffer").Buffer) + +},{"./bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/bigi.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js":[function(require,module,exports){ +var BigInteger = require('./bigi') + +//addons +require('./convert') + +module.exports = BigInteger +},{"./bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/bigi.js","./convert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/convert.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/package.json":[function(require,module,exports){ +module.exports={ + "_from": "bigi@^1.4.1", + "_id": "bigi@1.4.2", + "_inBundle": false, + "_integrity": "sha1-nGZalfiLiwj8Bc/XMfVhhZ1yWCU=", + "_location": "/peerplaysjs-lib/bigi", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "bigi@^1.4.1", + "name": "bigi", + "escapedName": "bigi", + "rawSpec": "^1.4.1", + "saveSpec": null, + "fetchSpec": "^1.4.1" + }, + "_requiredBy": [ + "/peerplaysjs-lib", + "/peerplaysjs-lib/ecurve" + ], + "_resolved": "https://registry.npmjs.org/bigi/-/bigi-1.4.2.tgz", + "_shasum": "9c665a95f88b8b08fc05cfd731f561859d725825", + "_spec": "bigi@^1.4.1", + "_where": "/Users/mseaward/Documents/code/peerplaysjs-lib", + "bugs": { + "url": "https://github.com/cryptocoinjs/bigi/issues" + }, + "bundleDependencies": false, + "dependencies": {}, + "deprecated": false, + "description": "Big integers.", + "devDependencies": { + "coveralls": "^2.11.2", + "istanbul": "^0.3.5", + "jshint": "^2.5.1", + "mocha": "^2.1.0", + "mochify": "^2.1.0" + }, + "homepage": "https://github.com/cryptocoinjs/bigi#readme", + "keywords": [ + "cryptography", + "math", + "bitcoin", + "arbitrary", + "precision", + "arithmetic", + "big", + "integer", + "int", + "number", + "biginteger", + "bigint", + "bignumber", + "decimal", + "float" + ], + "main": "./lib/index.js", + "name": "bigi", + "repository": { + "url": "git+https://github.com/cryptocoinjs/bigi.git", + "type": "git" + }, + "scripts": { + "browser-test": "mochify --wd -R spec", + "coverage": "istanbul cover ./node_modules/.bin/_mocha -- --reporter list test/*.js", + "coveralls": "npm run-script coverage && node ./node_modules/.bin/coveralls < coverage/lcov.info", + "jshint": "jshint --config jshint.json lib/*.js ; true", + "test": "_mocha -- test/*.js", + "unit": "mocha" + }, + "testling": { + "files": "test/*.js", + "harness": "mocha", + "browsers": [ + "ie/9..latest", + "firefox/latest", + "chrome/latest", + "safari/6.0..latest", + "iphone/6.0..latest", + "android-browser/4.2..latest" + ] + }, + "version": "1.4.2" +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browser-resolve/empty.js":[function(require,module,exports){ + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js":[function(require,module,exports){ +(function (global){ +/*! + * The buffer module from node.js, for the browser. + * + * @author Feross Aboukhadijeh + * @license MIT + */ +/* eslint-disable no-proto */ + +'use strict' + +var base64 = require('base64-js') +var ieee754 = require('ieee754') +var isArray = require('isarray') + +exports.Buffer = Buffer +exports.SlowBuffer = SlowBuffer +exports.INSPECT_MAX_BYTES = 50 + +/** + * If `Buffer.TYPED_ARRAY_SUPPORT`: + * === true Use Uint8Array implementation (fastest) + * === false Use Object implementation (most compatible, even IE6) + * + * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+, + * Opera 11.6+, iOS 4.2+. + * + * Due to various browser bugs, sometimes the Object implementation will be used even + * when the browser supports typed arrays. + * + * Note: + * + * - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances, + * See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438. + * + * - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function. + * + * - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of + * incorrect length in some situations. + + * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they + * get the Object implementation, which is slower but behaves correctly. + */ +Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined + ? global.TYPED_ARRAY_SUPPORT + : typedArraySupport() + +/* + * Export kMaxLength after typed array support is determined. + */ +exports.kMaxLength = kMaxLength() + +function typedArraySupport () { + try { + var arr = new Uint8Array(1) + arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} + return arr.foo() === 42 && // typed array instances can be augmented + typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` + arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` + } catch (e) { + return false + } +} + +function kMaxLength () { + return Buffer.TYPED_ARRAY_SUPPORT + ? 0x7fffffff + : 0x3fffffff +} + +function createBuffer (that, length) { + if (kMaxLength() < length) { + throw new RangeError('Invalid typed array length') + } + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = new Uint8Array(length) + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + if (that === null) { + that = new Buffer(length) + } + that.length = length + } + + return that +} + +/** + * The Buffer constructor returns instances of `Uint8Array` that have their + * prototype changed to `Buffer.prototype`. Furthermore, `Buffer` is a subclass of + * `Uint8Array`, so the returned instances will have all the node `Buffer` methods + * and the `Uint8Array` methods. Square bracket notation works as expected -- it + * returns a single octet. + * + * The `Uint8Array` prototype remains unmodified. + */ + +function Buffer (arg, encodingOrOffset, length) { + if (!Buffer.TYPED_ARRAY_SUPPORT && !(this instanceof Buffer)) { + return new Buffer(arg, encodingOrOffset, length) + } + + // Common case. + if (typeof arg === 'number') { + if (typeof encodingOrOffset === 'string') { + throw new Error( + 'If encoding is specified then the first argument must be a string' + ) + } + return allocUnsafe(this, arg) + } + return from(this, arg, encodingOrOffset, length) +} + +Buffer.poolSize = 8192 // not used by this implementation + +// TODO: Legacy, not needed anymore. Remove in next major version. +Buffer._augment = function (arr) { + arr.__proto__ = Buffer.prototype + return arr +} + +function from (that, value, encodingOrOffset, length) { + if (typeof value === 'number') { + throw new TypeError('"value" argument must not be a number') + } + + if (typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer) { + return fromArrayBuffer(that, value, encodingOrOffset, length) + } + + if (typeof value === 'string') { + return fromString(that, value, encodingOrOffset) + } + + return fromObject(that, value) +} + +/** + * Functionally equivalent to Buffer(arg, encoding) but throws a TypeError + * if value is a number. + * Buffer.from(str[, encoding]) + * Buffer.from(array) + * Buffer.from(buffer) + * Buffer.from(arrayBuffer[, byteOffset[, length]]) + **/ +Buffer.from = function (value, encodingOrOffset, length) { + return from(null, value, encodingOrOffset, length) +} + +if (Buffer.TYPED_ARRAY_SUPPORT) { + Buffer.prototype.__proto__ = Uint8Array.prototype + Buffer.__proto__ = Uint8Array + if (typeof Symbol !== 'undefined' && Symbol.species && + Buffer[Symbol.species] === Buffer) { + // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 + Object.defineProperty(Buffer, Symbol.species, { + value: null, + configurable: true + }) + } +} + +function assertSize (size) { + if (typeof size !== 'number') { + throw new TypeError('"size" argument must be a number') + } else if (size < 0) { + throw new RangeError('"size" argument must not be negative') + } +} + +function alloc (that, size, fill, encoding) { + assertSize(size) + if (size <= 0) { + return createBuffer(that, size) + } + if (fill !== undefined) { + // Only pay attention to encoding if it's a string. This + // prevents accidentally sending in a number that would + // be interpretted as a start offset. + return typeof encoding === 'string' + ? createBuffer(that, size).fill(fill, encoding) + : createBuffer(that, size).fill(fill) + } + return createBuffer(that, size) +} + +/** + * Creates a new filled Buffer instance. + * alloc(size[, fill[, encoding]]) + **/ +Buffer.alloc = function (size, fill, encoding) { + return alloc(null, size, fill, encoding) +} + +function allocUnsafe (that, size) { + assertSize(size) + that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) { + for (var i = 0; i < size; ++i) { + that[i] = 0 + } + } + return that +} + +/** + * Equivalent to Buffer(num), by default creates a non-zero-filled Buffer instance. + * */ +Buffer.allocUnsafe = function (size) { + return allocUnsafe(null, size) +} +/** + * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. + */ +Buffer.allocUnsafeSlow = function (size) { + return allocUnsafe(null, size) +} + +function fromString (that, string, encoding) { + if (typeof encoding !== 'string' || encoding === '') { + encoding = 'utf8' + } + + if (!Buffer.isEncoding(encoding)) { + throw new TypeError('"encoding" must be a valid string encoding') + } + + var length = byteLength(string, encoding) | 0 + that = createBuffer(that, length) + + var actual = that.write(string, encoding) + + if (actual !== length) { + // Writing a hex string, for example, that contains invalid characters will + // cause everything after the first invalid character to be ignored. (e.g. + // 'abxxcd' will be treated as 'ab') + that = that.slice(0, actual) + } + + return that +} + +function fromArrayLike (that, array) { + var length = array.length < 0 ? 0 : checked(array.length) | 0 + that = createBuffer(that, length) + for (var i = 0; i < length; i += 1) { + that[i] = array[i] & 255 + } + return that +} + +function fromArrayBuffer (that, array, byteOffset, length) { + array.byteLength // this throws if `array` is not a valid ArrayBuffer + + if (byteOffset < 0 || array.byteLength < byteOffset) { + throw new RangeError('\'offset\' is out of bounds') + } + + if (array.byteLength < byteOffset + (length || 0)) { + throw new RangeError('\'length\' is out of bounds') + } + + if (byteOffset === undefined && length === undefined) { + array = new Uint8Array(array) + } else if (length === undefined) { + array = new Uint8Array(array, byteOffset) + } else { + array = new Uint8Array(array, byteOffset, length) + } + + if (Buffer.TYPED_ARRAY_SUPPORT) { + // Return an augmented `Uint8Array` instance, for best performance + that = array + that.__proto__ = Buffer.prototype + } else { + // Fallback: Return an object instance of the Buffer class + that = fromArrayLike(that, array) + } + return that +} + +function fromObject (that, obj) { + if (Buffer.isBuffer(obj)) { + var len = checked(obj.length) | 0 + that = createBuffer(that, len) + + if (that.length === 0) { + return that + } + + obj.copy(that, 0, 0, len) + return that + } + + if (obj) { + if ((typeof ArrayBuffer !== 'undefined' && + obj.buffer instanceof ArrayBuffer) || 'length' in obj) { + if (typeof obj.length !== 'number' || isnan(obj.length)) { + return createBuffer(that, 0) + } + return fromArrayLike(that, obj) + } + + if (obj.type === 'Buffer' && isArray(obj.data)) { + return fromArrayLike(that, obj.data) + } + } + + throw new TypeError('First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.') +} + +function checked (length) { + // Note: cannot use `length < kMaxLength()` here because that fails when + // length is NaN (which is otherwise coerced to zero.) + if (length >= kMaxLength()) { + throw new RangeError('Attempt to allocate Buffer larger than maximum ' + + 'size: 0x' + kMaxLength().toString(16) + ' bytes') + } + return length | 0 +} + +function SlowBuffer (length) { + if (+length != length) { // eslint-disable-line eqeqeq + length = 0 + } + return Buffer.alloc(+length) +} + +Buffer.isBuffer = function isBuffer (b) { + return !!(b != null && b._isBuffer) +} + +Buffer.compare = function compare (a, b) { + if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { + throw new TypeError('Arguments must be Buffers') + } + + if (a === b) return 0 + + var x = a.length + var y = b.length + + for (var i = 0, len = Math.min(x, y); i < len; ++i) { + if (a[i] !== b[i]) { + x = a[i] + y = b[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +Buffer.isEncoding = function isEncoding (encoding) { + switch (String(encoding).toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'latin1': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return true + default: + return false + } +} + +Buffer.concat = function concat (list, length) { + if (!isArray(list)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + + if (list.length === 0) { + return Buffer.alloc(0) + } + + var i + if (length === undefined) { + length = 0 + for (i = 0; i < list.length; ++i) { + length += list[i].length + } + } + + var buffer = Buffer.allocUnsafe(length) + var pos = 0 + for (i = 0; i < list.length; ++i) { + var buf = list[i] + if (!Buffer.isBuffer(buf)) { + throw new TypeError('"list" argument must be an Array of Buffers') + } + buf.copy(buffer, pos) + pos += buf.length + } + return buffer +} + +function byteLength (string, encoding) { + if (Buffer.isBuffer(string)) { + return string.length + } + if (typeof ArrayBuffer !== 'undefined' && typeof ArrayBuffer.isView === 'function' && + (ArrayBuffer.isView(string) || string instanceof ArrayBuffer)) { + return string.byteLength + } + if (typeof string !== 'string') { + string = '' + string + } + + var len = string.length + if (len === 0) return 0 + + // Use a for loop to avoid recursion + var loweredCase = false + for (;;) { + switch (encoding) { + case 'ascii': + case 'latin1': + case 'binary': + return len + case 'utf8': + case 'utf-8': + case undefined: + return utf8ToBytes(string).length + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return len * 2 + case 'hex': + return len >>> 1 + case 'base64': + return base64ToBytes(string).length + default: + if (loweredCase) return utf8ToBytes(string).length // assume utf8 + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} +Buffer.byteLength = byteLength + +function slowToString (encoding, start, end) { + var loweredCase = false + + // No need to verify that "this.length <= MAX_UINT32" since it's a read-only + // property of a typed array. + + // This behaves neither like String nor Uint8Array in that we set start/end + // to their upper/lower bounds if the value passed is out of range. + // undefined is handled specially as per ECMA-262 6th Edition, + // Section 13.3.3.7 Runtime Semantics: KeyedBindingInitialization. + if (start === undefined || start < 0) { + start = 0 + } + // Return early if start > this.length. Done here to prevent potential uint32 + // coercion fail below. + if (start > this.length) { + return '' + } + + if (end === undefined || end > this.length) { + end = this.length + } + + if (end <= 0) { + return '' + } + + // Force coersion to uint32. This will also coerce falsey/NaN values to 0. + end >>>= 0 + start >>>= 0 + + if (end <= start) { + return '' + } + + if (!encoding) encoding = 'utf8' + + while (true) { + switch (encoding) { + case 'hex': + return hexSlice(this, start, end) + + case 'utf8': + case 'utf-8': + return utf8Slice(this, start, end) + + case 'ascii': + return asciiSlice(this, start, end) + + case 'latin1': + case 'binary': + return latin1Slice(this, start, end) + + case 'base64': + return base64Slice(this, start, end) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return utf16leSlice(this, start, end) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = (encoding + '').toLowerCase() + loweredCase = true + } + } +} + +// The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect +// Buffer instances. +Buffer.prototype._isBuffer = true + +function swap (b, n, m) { + var i = b[n] + b[n] = b[m] + b[m] = i +} + +Buffer.prototype.swap16 = function swap16 () { + var len = this.length + if (len % 2 !== 0) { + throw new RangeError('Buffer size must be a multiple of 16-bits') + } + for (var i = 0; i < len; i += 2) { + swap(this, i, i + 1) + } + return this +} + +Buffer.prototype.swap32 = function swap32 () { + var len = this.length + if (len % 4 !== 0) { + throw new RangeError('Buffer size must be a multiple of 32-bits') + } + for (var i = 0; i < len; i += 4) { + swap(this, i, i + 3) + swap(this, i + 1, i + 2) + } + return this +} + +Buffer.prototype.swap64 = function swap64 () { + var len = this.length + if (len % 8 !== 0) { + throw new RangeError('Buffer size must be a multiple of 64-bits') + } + for (var i = 0; i < len; i += 8) { + swap(this, i, i + 7) + swap(this, i + 1, i + 6) + swap(this, i + 2, i + 5) + swap(this, i + 3, i + 4) + } + return this +} + +Buffer.prototype.toString = function toString () { + var length = this.length | 0 + if (length === 0) return '' + if (arguments.length === 0) return utf8Slice(this, 0, length) + return slowToString.apply(this, arguments) +} + +Buffer.prototype.equals = function equals (b) { + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') + if (this === b) return true + return Buffer.compare(this, b) === 0 +} + +Buffer.prototype.inspect = function inspect () { + var str = '' + var max = exports.INSPECT_MAX_BYTES + if (this.length > 0) { + str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + if (this.length > max) str += ' ... ' + } + return '' +} + +Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { + if (!Buffer.isBuffer(target)) { + throw new TypeError('Argument must be a Buffer') + } + + if (start === undefined) { + start = 0 + } + if (end === undefined) { + end = target ? target.length : 0 + } + if (thisStart === undefined) { + thisStart = 0 + } + if (thisEnd === undefined) { + thisEnd = this.length + } + + if (start < 0 || end > target.length || thisStart < 0 || thisEnd > this.length) { + throw new RangeError('out of range index') + } + + if (thisStart >= thisEnd && start >= end) { + return 0 + } + if (thisStart >= thisEnd) { + return -1 + } + if (start >= end) { + return 1 + } + + start >>>= 0 + end >>>= 0 + thisStart >>>= 0 + thisEnd >>>= 0 + + if (this === target) return 0 + + var x = thisEnd - thisStart + var y = end - start + var len = Math.min(x, y) + + var thisCopy = this.slice(thisStart, thisEnd) + var targetCopy = target.slice(start, end) + + for (var i = 0; i < len; ++i) { + if (thisCopy[i] !== targetCopy[i]) { + x = thisCopy[i] + y = targetCopy[i] + break + } + } + + if (x < y) return -1 + if (y < x) return 1 + return 0 +} + +// Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, +// OR the last index of `val` in `buffer` at offset <= `byteOffset`. +// +// Arguments: +// - buffer - a Buffer to search +// - val - a string, Buffer, or number +// - byteOffset - an index into `buffer`; will be clamped to an int32 +// - encoding - an optional encoding, relevant is val is a string +// - dir - true for indexOf, false for lastIndexOf +function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { + // Empty buffer means no match + if (buffer.length === 0) return -1 + + // Normalize byteOffset + if (typeof byteOffset === 'string') { + encoding = byteOffset + byteOffset = 0 + } else if (byteOffset > 0x7fffffff) { + byteOffset = 0x7fffffff + } else if (byteOffset < -0x80000000) { + byteOffset = -0x80000000 + } + byteOffset = +byteOffset // Coerce to Number. + if (isNaN(byteOffset)) { + // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer + byteOffset = dir ? 0 : (buffer.length - 1) + } + + // Normalize byteOffset: negative offsets start from the end of the buffer + if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset >= buffer.length) { + if (dir) return -1 + else byteOffset = buffer.length - 1 + } else if (byteOffset < 0) { + if (dir) byteOffset = 0 + else return -1 + } + + // Normalize val + if (typeof val === 'string') { + val = Buffer.from(val, encoding) + } + + // Finally, search either indexOf (if dir is true) or lastIndexOf + if (Buffer.isBuffer(val)) { + // Special case: looking for empty string/buffer always fails + if (val.length === 0) { + return -1 + } + return arrayIndexOf(buffer, val, byteOffset, encoding, dir) + } else if (typeof val === 'number') { + val = val & 0xFF // Search for a byte value [0-255] + if (Buffer.TYPED_ARRAY_SUPPORT && + typeof Uint8Array.prototype.indexOf === 'function') { + if (dir) { + return Uint8Array.prototype.indexOf.call(buffer, val, byteOffset) + } else { + return Uint8Array.prototype.lastIndexOf.call(buffer, val, byteOffset) + } + } + return arrayIndexOf(buffer, [ val ], byteOffset, encoding, dir) + } + + throw new TypeError('val must be string, number or Buffer') +} + +function arrayIndexOf (arr, val, byteOffset, encoding, dir) { + var indexSize = 1 + var arrLength = arr.length + var valLength = val.length + + if (encoding !== undefined) { + encoding = String(encoding).toLowerCase() + if (encoding === 'ucs2' || encoding === 'ucs-2' || + encoding === 'utf16le' || encoding === 'utf-16le') { + if (arr.length < 2 || val.length < 2) { + return -1 + } + indexSize = 2 + arrLength /= 2 + valLength /= 2 + byteOffset /= 2 + } + } + + function read (buf, i) { + if (indexSize === 1) { + return buf[i] + } else { + return buf.readUInt16BE(i * indexSize) + } + } + + var i + if (dir) { + var foundIndex = -1 + for (i = byteOffset; i < arrLength; i++) { + if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { + if (foundIndex === -1) foundIndex = i + if (i - foundIndex + 1 === valLength) return foundIndex * indexSize + } else { + if (foundIndex !== -1) i -= i - foundIndex + foundIndex = -1 + } + } + } else { + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + for (i = byteOffset; i >= 0; i--) { + var found = true + for (var j = 0; j < valLength; j++) { + if (read(arr, i + j) !== read(val, j)) { + found = false + break + } + } + if (found) return i + } + } + + return -1 +} + +Buffer.prototype.includes = function includes (val, byteOffset, encoding) { + return this.indexOf(val, byteOffset, encoding) !== -1 +} + +Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, true) +} + +Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { + return bidirectionalIndexOf(this, val, byteOffset, encoding, false) +} + +function hexWrite (buf, string, offset, length) { + offset = Number(offset) || 0 + var remaining = buf.length - offset + if (!length) { + length = remaining + } else { + length = Number(length) + if (length > remaining) { + length = remaining + } + } + + // must be an even number of digits + var strLen = string.length + if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') + + if (length > strLen / 2) { + length = strLen / 2 + } + for (var i = 0; i < length; ++i) { + var parsed = parseInt(string.substr(i * 2, 2), 16) + if (isNaN(parsed)) return i + buf[offset + i] = parsed + } + return i +} + +function utf8Write (buf, string, offset, length) { + return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length) +} + +function asciiWrite (buf, string, offset, length) { + return blitBuffer(asciiToBytes(string), buf, offset, length) +} + +function latin1Write (buf, string, offset, length) { + return asciiWrite(buf, string, offset, length) +} + +function base64Write (buf, string, offset, length) { + return blitBuffer(base64ToBytes(string), buf, offset, length) +} + +function ucs2Write (buf, string, offset, length) { + return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length) +} + +Buffer.prototype.write = function write (string, offset, length, encoding) { + // Buffer#write(string) + if (offset === undefined) { + encoding = 'utf8' + length = this.length + offset = 0 + // Buffer#write(string, encoding) + } else if (length === undefined && typeof offset === 'string') { + encoding = offset + length = this.length + offset = 0 + // Buffer#write(string, offset[, length][, encoding]) + } else if (isFinite(offset)) { + offset = offset | 0 + if (isFinite(length)) { + length = length | 0 + if (encoding === undefined) encoding = 'utf8' + } else { + encoding = length + length = undefined + } + // legacy write(string, encoding, offset, length) - remove in v0.13 + } else { + throw new Error( + 'Buffer.write(string, encoding, offset[, length]) is no longer supported' + ) + } + + var remaining = this.length - offset + if (length === undefined || length > remaining) length = remaining + + if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { + throw new RangeError('Attempt to write outside buffer bounds') + } + + if (!encoding) encoding = 'utf8' + + var loweredCase = false + for (;;) { + switch (encoding) { + case 'hex': + return hexWrite(this, string, offset, length) + + case 'utf8': + case 'utf-8': + return utf8Write(this, string, offset, length) + + case 'ascii': + return asciiWrite(this, string, offset, length) + + case 'latin1': + case 'binary': + return latin1Write(this, string, offset, length) + + case 'base64': + // Warning: maxLength not taken into account in base64Write + return base64Write(this, string, offset, length) + + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return ucs2Write(this, string, offset, length) + + default: + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) + encoding = ('' + encoding).toLowerCase() + loweredCase = true + } + } +} + +Buffer.prototype.toJSON = function toJSON () { + return { + type: 'Buffer', + data: Array.prototype.slice.call(this._arr || this, 0) + } +} + +function base64Slice (buf, start, end) { + if (start === 0 && end === buf.length) { + return base64.fromByteArray(buf) + } else { + return base64.fromByteArray(buf.slice(start, end)) + } +} + +function utf8Slice (buf, start, end) { + end = Math.min(buf.length, end) + var res = [] + + var i = start + while (i < end) { + var firstByte = buf[i] + var codePoint = null + var bytesPerSequence = (firstByte > 0xEF) ? 4 + : (firstByte > 0xDF) ? 3 + : (firstByte > 0xBF) ? 2 + : 1 + + if (i + bytesPerSequence <= end) { + var secondByte, thirdByte, fourthByte, tempCodePoint + + switch (bytesPerSequence) { + case 1: + if (firstByte < 0x80) { + codePoint = firstByte + } + break + case 2: + secondByte = buf[i + 1] + if ((secondByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + if (tempCodePoint > 0x7F) { + codePoint = tempCodePoint + } + } + break + case 3: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { + codePoint = tempCodePoint + } + } + break + case 4: + secondByte = buf[i + 1] + thirdByte = buf[i + 2] + fourthByte = buf[i + 3] + if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { + codePoint = tempCodePoint + } + } + } + } + + if (codePoint === null) { + // we did not generate a valid codePoint so insert a + // replacement char (U+FFFD) and advance only 1 byte + codePoint = 0xFFFD + bytesPerSequence = 1 + } else if (codePoint > 0xFFFF) { + // encode to utf16 (surrogate pair dance) + codePoint -= 0x10000 + res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint = 0xDC00 | codePoint & 0x3FF + } + + res.push(codePoint) + i += bytesPerSequence + } + + return decodeCodePointsArray(res) +} + +// Based on http://stackoverflow.com/a/22747272/680742, the browser with +// the lowest limit is Chrome, with 0x10000 args. +// We go 1 magnitude less, for safety +var MAX_ARGUMENTS_LENGTH = 0x1000 + +function decodeCodePointsArray (codePoints) { + var len = codePoints.length + if (len <= MAX_ARGUMENTS_LENGTH) { + return String.fromCharCode.apply(String, codePoints) // avoid extra slice() + } + + // Decode in chunks to avoid "call stack size exceeded". + var res = '' + var i = 0 + while (i < len) { + res += String.fromCharCode.apply( + String, + codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH) + ) + } + return res +} + +function asciiSlice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i] & 0x7F) + } + return ret +} + +function latin1Slice (buf, start, end) { + var ret = '' + end = Math.min(buf.length, end) + + for (var i = start; i < end; ++i) { + ret += String.fromCharCode(buf[i]) + } + return ret +} + +function hexSlice (buf, start, end) { + var len = buf.length + + if (!start || start < 0) start = 0 + if (!end || end < 0 || end > len) end = len + + var out = '' + for (var i = start; i < end; ++i) { + out += toHex(buf[i]) + } + return out +} + +function utf16leSlice (buf, start, end) { + var bytes = buf.slice(start, end) + var res = '' + for (var i = 0; i < bytes.length; i += 2) { + res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) + } + return res +} + +Buffer.prototype.slice = function slice (start, end) { + var len = this.length + start = ~~start + end = end === undefined ? len : ~~end + + if (start < 0) { + start += len + if (start < 0) start = 0 + } else if (start > len) { + start = len + } + + if (end < 0) { + end += len + if (end < 0) end = 0 + } else if (end > len) { + end = len + } + + if (end < start) end = start + + var newBuf + if (Buffer.TYPED_ARRAY_SUPPORT) { + newBuf = this.subarray(start, end) + newBuf.__proto__ = Buffer.prototype + } else { + var sliceLen = end - start + newBuf = new Buffer(sliceLen, undefined) + for (var i = 0; i < sliceLen; ++i) { + newBuf[i] = this[i + start] + } + } + + return newBuf +} + +/* + * Need to make sure that buffer isn't trying to write out of bounds. + */ +function checkOffset (offset, ext, length) { + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') +} + +Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + + return val +} + +Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + checkOffset(offset, byteLength, this.length) + } + + var val = this[offset + --byteLength] + var mul = 1 + while (byteLength > 0 && (mul *= 0x100)) { + val += this[offset + --byteLength] * mul + } + + return val +} + +Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + return this[offset] +} + +Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return this[offset] | (this[offset + 1] << 8) +} + +Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + return (this[offset] << 8) | this[offset + 1] +} + +Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return ((this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16)) + + (this[offset + 3] * 0x1000000) +} + +Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] * 0x1000000) + + ((this[offset + 1] << 16) | + (this[offset + 2] << 8) | + this[offset + 3]) +} + +Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var val = this[offset] + var mul = 1 + var i = 0 + while (++i < byteLength && (mul *= 0x100)) { + val += this[offset + i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) checkOffset(offset, byteLength, this.length) + + var i = byteLength + var mul = 1 + var val = this[offset + --i] + while (i > 0 && (mul *= 0x100)) { + val += this[offset + --i] * mul + } + mul *= 0x80 + + if (val >= mul) val -= Math.pow(2, 8 * byteLength) + + return val +} + +Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { + if (!noAssert) checkOffset(offset, 1, this.length) + if (!(this[offset] & 0x80)) return (this[offset]) + return ((0xff - this[offset] + 1) * -1) +} + +Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset] | (this[offset + 1] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 2, this.length) + var val = this[offset + 1] | (this[offset] << 8) + return (val & 0x8000) ? val | 0xFFFF0000 : val +} + +Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset]) | + (this[offset + 1] << 8) | + (this[offset + 2] << 16) | + (this[offset + 3] << 24) +} + +Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + + return (this[offset] << 24) | + (this[offset + 1] << 16) | + (this[offset + 2] << 8) | + (this[offset + 3]) +} + +Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, true, 23, 4) +} + +Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 4, this.length) + return ieee754.read(this, offset, false, 23, 4) +} + +Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, true, 52, 8) +} + +Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { + if (!noAssert) checkOffset(offset, 8, this.length) + return ieee754.read(this, offset, false, 52, 8) +} + +function checkInt (buf, value, offset, ext, max, min) { + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (offset + ext > buf.length) throw new RangeError('Index out of range') +} + +Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var mul = 1 + var i = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + byteLength = byteLength | 0 + if (!noAssert) { + var maxBytes = Math.pow(2, 8 * byteLength) - 1 + checkInt(this, value, offset, byteLength, maxBytes, 0) + } + + var i = byteLength - 1 + var mul = 1 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + this[offset + i] = (value / mul) & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + this[offset] = (value & 0xff) + return offset + 1 +} + +function objectWriteUInt16 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { + buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> + (littleEndian ? i : 1 - i) * 8 + } +} + +Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +function objectWriteUInt32 (buf, value, offset, littleEndian) { + if (value < 0) value = 0xffffffff + value + 1 + for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { + buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff + } +} + +Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset + 3] = (value >>> 24) + this[offset + 2] = (value >>> 16) + this[offset + 1] = (value >>> 8) + this[offset] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = 0 + var mul = 1 + var sub = 0 + this[offset] = value & 0xFF + while (++i < byteLength && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) { + var limit = Math.pow(2, 8 * byteLength - 1) + + checkInt(this, value, offset, byteLength, limit - 1, -limit) + } + + var i = byteLength - 1 + var mul = 1 + var sub = 0 + this[offset + i] = value & 0xFF + while (--i >= 0 && (mul *= 0x100)) { + if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { + sub = 1 + } + this[offset + i] = ((value / mul) >> 0) - sub & 0xFF + } + + return offset + byteLength +} + +Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) + if (value < 0) value = 0xff + value + 1 + this[offset] = (value & 0xff) + return offset + 1 +} + +Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + } else { + objectWriteUInt16(this, value, offset, true) + } + return offset + 2 +} + +Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 8) + this[offset + 1] = (value & 0xff) + } else { + objectWriteUInt16(this, value, offset, false) + } + return offset + 2 +} + +Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value & 0xff) + this[offset + 1] = (value >>> 8) + this[offset + 2] = (value >>> 16) + this[offset + 3] = (value >>> 24) + } else { + objectWriteUInt32(this, value, offset, true) + } + return offset + 4 +} + +Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { + value = +value + offset = offset | 0 + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + if (value < 0) value = 0xffffffff + value + 1 + if (Buffer.TYPED_ARRAY_SUPPORT) { + this[offset] = (value >>> 24) + this[offset + 1] = (value >>> 16) + this[offset + 2] = (value >>> 8) + this[offset + 3] = (value & 0xff) + } else { + objectWriteUInt32(this, value, offset, false) + } + return offset + 4 +} + +function checkIEEE754 (buf, value, offset, ext, max, min) { + if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset < 0) throw new RangeError('Index out of range') +} + +function writeFloat (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) + } + ieee754.write(buf, value, offset, littleEndian, 23, 4) + return offset + 4 +} + +Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { + return writeFloat(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { + return writeFloat(this, value, offset, false, noAssert) +} + +function writeDouble (buf, value, offset, littleEndian, noAssert) { + if (!noAssert) { + checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) + } + ieee754.write(buf, value, offset, littleEndian, 52, 8) + return offset + 8 +} + +Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { + return writeDouble(this, value, offset, true, noAssert) +} + +Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { + return writeDouble(this, value, offset, false, noAssert) +} + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function copy (target, targetStart, start, end) { + if (!start) start = 0 + if (!end && end !== 0) end = this.length + if (targetStart >= target.length) targetStart = target.length + if (!targetStart) targetStart = 0 + if (end > 0 && end < start) end = start + + // Copy 0 bytes; we're done + if (end === start) return 0 + if (target.length === 0 || this.length === 0) return 0 + + // Fatal error conditions + if (targetStart < 0) { + throw new RangeError('targetStart out of bounds') + } + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') + if (end < 0) throw new RangeError('sourceEnd out of bounds') + + // Are we oob? + if (end > this.length) end = this.length + if (target.length - targetStart < end - start) { + end = target.length - targetStart + start + } + + var len = end - start + var i + + if (this === target && start < targetStart && targetStart < end) { + // descending copy from end + for (i = len - 1; i >= 0; --i) { + target[i + targetStart] = this[i + start] + } + } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) { + // ascending copy from start + for (i = 0; i < len; ++i) { + target[i + targetStart] = this[i + start] + } + } else { + Uint8Array.prototype.set.call( + target, + this.subarray(start, start + len), + targetStart + ) + } + + return len +} + +// Usage: +// buffer.fill(number[, offset[, end]]) +// buffer.fill(buffer[, offset[, end]]) +// buffer.fill(string[, offset[, end]][, encoding]) +Buffer.prototype.fill = function fill (val, start, end, encoding) { + // Handle string cases: + if (typeof val === 'string') { + if (typeof start === 'string') { + encoding = start + start = 0 + end = this.length + } else if (typeof end === 'string') { + encoding = end + end = this.length + } + if (val.length === 1) { + var code = val.charCodeAt(0) + if (code < 256) { + val = code + } + } + if (encoding !== undefined && typeof encoding !== 'string') { + throw new TypeError('encoding must be a string') + } + if (typeof encoding === 'string' && !Buffer.isEncoding(encoding)) { + throw new TypeError('Unknown encoding: ' + encoding) + } + } else if (typeof val === 'number') { + val = val & 255 + } + + // Invalid ranges are not set to a default, so can range check early. + if (start < 0 || this.length < start || this.length < end) { + throw new RangeError('Out of range index') + } + + if (end <= start) { + return this + } + + start = start >>> 0 + end = end === undefined ? this.length : end >>> 0 + + if (!val) val = 0 + + var i + if (typeof val === 'number') { + for (i = start; i < end; ++i) { + this[i] = val + } + } else { + var bytes = Buffer.isBuffer(val) + ? val + : utf8ToBytes(new Buffer(val, encoding).toString()) + var len = bytes.length + for (i = 0; i < end - start; ++i) { + this[i + start] = bytes[i % len] + } + } + + return this +} + +// HELPER FUNCTIONS +// ================ + +var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g + +function base64clean (str) { + // Node strips out invalid characters like \n and \t from the string, base64-js does not + str = stringtrim(str).replace(INVALID_BASE64_RE, '') + // Node converts strings with length < 2 to '' + if (str.length < 2) return '' + // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not + while (str.length % 4 !== 0) { + str = str + '=' + } + return str +} + +function stringtrim (str) { + if (str.trim) return str.trim() + return str.replace(/^\s+|\s+$/g, '') +} + +function toHex (n) { + if (n < 16) return '0' + n.toString(16) + return n.toString(16) +} + +function utf8ToBytes (string, units) { + units = units || Infinity + var codePoint + var length = string.length + var leadSurrogate = null + var bytes = [] + + for (var i = 0; i < length; ++i) { + codePoint = string.charCodeAt(i) + + // is surrogate component + if (codePoint > 0xD7FF && codePoint < 0xE000) { + // last char was a lead + if (!leadSurrogate) { + // no lead yet + if (codePoint > 0xDBFF) { + // unexpected trail + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } else if (i + 1 === length) { + // unpaired lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + continue + } + + // valid lead + leadSurrogate = codePoint + + continue + } + + // 2 leads in a row + if (codePoint < 0xDC00) { + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + leadSurrogate = codePoint + continue + } + + // valid surrogate pair + codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000 + } else if (leadSurrogate) { + // valid bmp char, but last char was a lead + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + } + + leadSurrogate = null + + // encode utf8 + if (codePoint < 0x80) { + if ((units -= 1) < 0) break + bytes.push(codePoint) + } else if (codePoint < 0x800) { + if ((units -= 2) < 0) break + bytes.push( + codePoint >> 0x6 | 0xC0, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x10000) { + if ((units -= 3) < 0) break + bytes.push( + codePoint >> 0xC | 0xE0, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else if (codePoint < 0x110000) { + if ((units -= 4) < 0) break + bytes.push( + codePoint >> 0x12 | 0xF0, + codePoint >> 0xC & 0x3F | 0x80, + codePoint >> 0x6 & 0x3F | 0x80, + codePoint & 0x3F | 0x80 + ) + } else { + throw new Error('Invalid code point') + } + } + + return bytes +} + +function asciiToBytes (str) { + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push(str.charCodeAt(i) & 0xFF) + } + return byteArray +} + +function utf16leToBytes (str, units) { + var c, hi, lo + var byteArray = [] + for (var i = 0; i < str.length; ++i) { + if ((units -= 2) < 0) break + + c = str.charCodeAt(i) + hi = c >> 8 + lo = c % 256 + byteArray.push(lo) + byteArray.push(hi) + } + + return byteArray +} + +function base64ToBytes (str) { + return base64.toByteArray(base64clean(str)) +} + +function blitBuffer (src, dst, offset, length) { + for (var i = 0; i < length; ++i) { + if ((i + offset >= dst.length) || (i >= src.length)) break + dst[i + offset] = src[i] + } + return i +} + +function isnan (val) { + return val !== val // eslint-disable-line no-self-compare +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"base64-js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/base64-js/index.js","ieee754":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ieee754/index.js","isarray":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/isarray/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/string_decoder/index.js":[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var Buffer = require('buffer').Buffer; + +var isBufferEncoding = Buffer.isEncoding + || function(encoding) { + switch (encoding && encoding.toLowerCase()) { + case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true; + default: return false; + } + } + + +function assertEncoding(encoding) { + if (encoding && !isBufferEncoding(encoding)) { + throw new Error('Unknown encoding: ' + encoding); + } +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. CESU-8 is handled as part of the UTF-8 encoding. +// +// @TODO Handling all encodings inside a single object makes it very difficult +// to reason about this code, so it should be split up in the future. +// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code +// points as used by CESU-8. +var StringDecoder = exports.StringDecoder = function(encoding) { + this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, ''); + assertEncoding(encoding); + switch (this.encoding) { + case 'utf8': + // CESU-8 represents each of Surrogate Pair by 3-bytes + this.surrogateSize = 3; + break; + case 'ucs2': + case 'utf16le': + // UTF-16 represents each of Surrogate Pair by 2-bytes + this.surrogateSize = 2; + this.detectIncompleteChar = utf16DetectIncompleteChar; + break; + case 'base64': + // Base-64 stores 3 bytes in 4 chars, and pads the remainder. + this.surrogateSize = 3; + this.detectIncompleteChar = base64DetectIncompleteChar; + break; + default: + this.write = passThroughWrite; + return; + } + + // Enough space to store all bytes of a single character. UTF-8 needs 4 + // bytes, but CESU-8 may require up to 6 (3 bytes per surrogate). + this.charBuffer = new Buffer(6); + // Number of bytes received for the current incomplete multi-byte character. + this.charReceived = 0; + // Number of bytes expected for the current incomplete multi-byte character. + this.charLength = 0; +}; + + +// write decodes the given buffer and returns it as JS string that is +// guaranteed to not contain any partial multi-byte characters. Any partial +// character found at the end of the buffer is buffered up, and will be +// returned when calling write again with the remaining bytes. +// +// Note: Converting a Buffer containing an orphan surrogate to a String +// currently works, but converting a String to a Buffer (via `new Buffer`, or +// Buffer#write) will replace incomplete surrogates with the unicode +// replacement character. See https://codereview.chromium.org/121173009/ . +StringDecoder.prototype.write = function(buffer) { + var charStr = ''; + // if our last write ended with an incomplete multibyte character + while (this.charLength) { + // determine how many remaining bytes this buffer has to offer for this char + var available = (buffer.length >= this.charLength - this.charReceived) ? + this.charLength - this.charReceived : + buffer.length; + + // add the new bytes to the char buffer + buffer.copy(this.charBuffer, this.charReceived, 0, available); + this.charReceived += available; + + if (this.charReceived < this.charLength) { + // still not enough chars in this buffer? wait for more ... + return ''; + } + + // remove bytes belonging to the current character from the buffer + buffer = buffer.slice(available, buffer.length); + + // get the character that was split + charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding); + + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + var charCode = charStr.charCodeAt(charStr.length - 1); + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + this.charLength += this.surrogateSize; + charStr = ''; + continue; + } + this.charReceived = this.charLength = 0; + + // if there are no more bytes in this buffer, just emit our char + if (buffer.length === 0) { + return charStr; + } + break; + } + + // determine and set charLength / charReceived + this.detectIncompleteChar(buffer); + + var end = buffer.length; + if (this.charLength) { + // buffer the incomplete character bytes we got + buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end); + end -= this.charReceived; + } + + charStr += buffer.toString(this.encoding, 0, end); + + var end = charStr.length - 1; + var charCode = charStr.charCodeAt(end); + // CESU-8: lead surrogate (D800-DBFF) is also the incomplete character + if (charCode >= 0xD800 && charCode <= 0xDBFF) { + var size = this.surrogateSize; + this.charLength += size; + this.charReceived += size; + this.charBuffer.copy(this.charBuffer, size, 0, size); + buffer.copy(this.charBuffer, 0, 0, size); + return charStr.substring(0, end); + } + + // or just emit the charStr + return charStr; +}; + +// detectIncompleteChar determines if there is an incomplete UTF-8 character at +// the end of the given buffer. If so, it sets this.charLength to the byte +// length that character, and sets this.charReceived to the number of bytes +// that are available for this character. +StringDecoder.prototype.detectIncompleteChar = function(buffer) { + // determine how many bytes we have to check at the end of this buffer + var i = (buffer.length >= 3) ? 3 : buffer.length; + + // Figure out if one of the last i bytes of our buffer announces an + // incomplete char. + for (; i > 0; i--) { + var c = buffer[buffer.length - i]; + + // See http://en.wikipedia.org/wiki/UTF-8#Description + + // 110XXXXX + if (i == 1 && c >> 5 == 0x06) { + this.charLength = 2; + break; + } + + // 1110XXXX + if (i <= 2 && c >> 4 == 0x0E) { + this.charLength = 3; + break; + } + + // 11110XXX + if (i <= 3 && c >> 3 == 0x1E) { + this.charLength = 4; + break; + } + } + this.charReceived = i; +}; + +StringDecoder.prototype.end = function(buffer) { + var res = ''; + if (buffer && buffer.length) + res = this.write(buffer); + + if (this.charReceived) { + var cr = this.charReceived; + var buf = this.charBuffer; + var enc = this.encoding; + res += buf.slice(0, cr).toString(enc); + } + + return res; +}; + +function passThroughWrite(buffer) { + return buffer.toString(this.encoding); +} + +function utf16DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 2; + this.charLength = this.charReceived ? 2 : 0; +} + +function base64DetectIncompleteChar(buffer) { + this.charReceived = buffer.length % 3; + this.charLength = this.charReceived ? 3 : 0; +} + +},{"buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bs58/index.js":[function(require,module,exports){ +var basex = require('base-x') +var ALPHABET = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' + +module.exports = basex(ALPHABET) + +},{"base-x":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/base-x/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bytebuffer/dist/bytebuffer.js":[function(require,module,exports){ +/* + Copyright 2013-2014 Daniel Wirtz + + 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. + */ + +/** + * @license bytebuffer.js (c) 2015 Daniel Wirtz + * Backing buffer: ArrayBuffer, Accessor: Uint8Array + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/bytebuffer.js for details + */ +(function(global, factory) { + + /* AMD */ if (typeof define === 'function' && define["amd"]) + define(["long"], factory); + /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) + module['exports'] = (function() { + var Long; try { Long = require("long"); } catch (e) {} + return factory(Long); + })(); + /* Global */ else + (global["dcodeIO"] = global["dcodeIO"] || {})["ByteBuffer"] = factory(global["dcodeIO"]["Long"]); + +})(this, function(Long) { + "use strict"; + + /** + * Constructs a new ByteBuffer. + * @class The swiss army knife for binary data in JavaScript. + * @exports ByteBuffer + * @constructor + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @expose + */ + var ByteBuffer = function(capacity, littleEndian, noAssert) { + if (typeof capacity === 'undefined') + capacity = ByteBuffer.DEFAULT_CAPACITY; + if (typeof littleEndian === 'undefined') + littleEndian = ByteBuffer.DEFAULT_ENDIAN; + if (typeof noAssert === 'undefined') + noAssert = ByteBuffer.DEFAULT_NOASSERT; + if (!noAssert) { + capacity = capacity | 0; + if (capacity < 0) + throw RangeError("Illegal capacity"); + littleEndian = !!littleEndian; + noAssert = !!noAssert; + } + + /** + * Backing ArrayBuffer. + * @type {!ArrayBuffer} + * @expose + */ + this.buffer = capacity === 0 ? EMPTY_BUFFER : new ArrayBuffer(capacity); + + /** + * Uint8Array utilized to manipulate the backing buffer. Becomes `null` if the backing buffer has a capacity of `0`. + * @type {?Uint8Array} + * @expose + */ + this.view = capacity === 0 ? null : new Uint8Array(this.buffer); + + /** + * Absolute read/write offset. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.offset = 0; + + /** + * Marked offset. + * @type {number} + * @expose + * @see ByteBuffer#mark + * @see ByteBuffer#reset + */ + this.markedOffset = -1; + + /** + * Absolute limit of the contained data. Set to the backing buffer's capacity upon allocation. + * @type {number} + * @expose + * @see ByteBuffer#flip + * @see ByteBuffer#clear + */ + this.limit = capacity; + + /** + * Whether to use little endian byte order, defaults to `false` for big endian. + * @type {boolean} + * @expose + */ + this.littleEndian = littleEndian; + + /** + * Whether to skip assertions of offsets and values, defaults to `false`. + * @type {boolean} + * @expose + */ + this.noAssert = noAssert; + }; + + /** + * ByteBuffer version. + * @type {string} + * @const + * @expose + */ + ByteBuffer.VERSION = "5.0.1"; + + /** + * Little endian constant that can be used instead of its boolean value. Evaluates to `true`. + * @type {boolean} + * @const + * @expose + */ + ByteBuffer.LITTLE_ENDIAN = true; + + /** + * Big endian constant that can be used instead of its boolean value. Evaluates to `false`. + * @type {boolean} + * @const + * @expose + */ + ByteBuffer.BIG_ENDIAN = false; + + /** + * Default initial capacity of `16`. + * @type {number} + * @expose + */ + ByteBuffer.DEFAULT_CAPACITY = 16; + + /** + * Default endianess of `false` for big endian. + * @type {boolean} + * @expose + */ + ByteBuffer.DEFAULT_ENDIAN = ByteBuffer.BIG_ENDIAN; + + /** + * Default no assertions flag of `false`. + * @type {boolean} + * @expose + */ + ByteBuffer.DEFAULT_NOASSERT = false; + + /** + * A `Long` class for representing a 64-bit two's-complement integer value. May be `null` if Long.js has not been loaded + * and int64 support is not available. + * @type {?Long} + * @const + * @see https://github.com/dcodeIO/long.js + * @expose + */ + ByteBuffer.Long = Long || null; + + /** + * @alias ByteBuffer.prototype + * @inner + */ + var ByteBufferPrototype = ByteBuffer.prototype; + + /** + * An indicator used to reliably determine if an object is a ByteBuffer or not. + * @type {boolean} + * @const + * @expose + * @private + */ + ByteBufferPrototype.__isByteBuffer__; + + Object.defineProperty(ByteBufferPrototype, "__isByteBuffer__", { + value: true, + enumerable: false, + configurable: false + }); + + // helpers + + /** + * @type {!ArrayBuffer} + * @inner + */ + var EMPTY_BUFFER = new ArrayBuffer(0); + + /** + * String.fromCharCode reference for compile-time renaming. + * @type {function(...number):string} + * @inner + */ + var stringFromCharCode = String.fromCharCode; + + /** + * Creates a source function for a string. + * @param {string} s String to read from + * @returns {function():number|null} Source function returning the next char code respectively `null` if there are + * no more characters left. + * @throws {TypeError} If the argument is invalid + * @inner + */ + function stringSource(s) { + var i=0; return function() { + return i < s.length ? s.charCodeAt(i++) : null; + }; + } + + /** + * Creates a destination function for a string. + * @returns {function(number=):undefined|string} Destination function successively called with the next char code. + * Returns the final string when called without arguments. + * @inner + */ + function stringDestination() { + var cs = [], ps = []; return function() { + if (arguments.length === 0) + return ps.join('')+stringFromCharCode.apply(String, cs); + if (cs.length + arguments.length > 1024) + ps.push(stringFromCharCode.apply(String, cs)), + cs.length = 0; + Array.prototype.push.apply(cs, arguments); + }; + } + + /** + * Gets the accessor type. + * @returns {Function} `Buffer` under node.js, `Uint8Array` respectively `DataView` in the browser (classes) + * @expose + */ + ByteBuffer.accessor = function() { + return Uint8Array; + }; + /** + * Allocates a new ByteBuffer backed by a buffer of the specified capacity. + * @param {number=} capacity Initial capacity. Defaults to {@link ByteBuffer.DEFAULT_CAPACITY}. + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} + * @expose + */ + ByteBuffer.allocate = function(capacity, littleEndian, noAssert) { + return new ByteBuffer(capacity, littleEndian, noAssert); + }; + + /** + * Concatenates multiple ByteBuffers into one. + * @param {!Array.} buffers Buffers to concatenate + * @param {(string|boolean)=} encoding String encoding if `buffers` contains a string ("base64", "hex", "binary", + * defaults to "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order for the resulting ByteBuffer. Defaults + * to {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values for the resulting ByteBuffer. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} Concatenated ByteBuffer + * @expose + */ + ByteBuffer.concat = function(buffers, encoding, littleEndian, noAssert) { + if (typeof encoding === 'boolean' || typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + var capacity = 0; + for (var i=0, k=buffers.length, length; i 0) capacity += length; + } + if (capacity === 0) + return new ByteBuffer(0, littleEndian, noAssert); + var bb = new ByteBuffer(capacity, littleEndian, noAssert), + bi; + i=0; while (i} buffer Anything that can be wrapped + * @param {(string|boolean)=} encoding String encoding if `buffer` is a string ("base64", "hex", "binary", defaults to + * "utf8") + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} A ByteBuffer wrapping `buffer` + * @expose + */ + ByteBuffer.wrap = function(buffer, encoding, littleEndian, noAssert) { + if (typeof encoding !== 'string') { + noAssert = littleEndian; + littleEndian = encoding; + encoding = undefined; + } + if (typeof buffer === 'string') { + if (typeof encoding === 'undefined') + encoding = "utf8"; + switch (encoding) { + case "base64": + return ByteBuffer.fromBase64(buffer, littleEndian); + case "hex": + return ByteBuffer.fromHex(buffer, littleEndian); + case "binary": + return ByteBuffer.fromBinary(buffer, littleEndian); + case "utf8": + return ByteBuffer.fromUTF8(buffer, littleEndian); + case "debug": + return ByteBuffer.fromDebug(buffer, littleEndian); + default: + throw Error("Unsupported encoding: "+encoding); + } + } + if (buffer === null || typeof buffer !== 'object') + throw TypeError("Illegal buffer"); + var bb; + if (ByteBuffer.isByteBuffer(buffer)) { + bb = ByteBufferPrototype.clone.call(buffer); + bb.markedOffset = -1; + return bb; + } + if (buffer instanceof Uint8Array) { // Extract ArrayBuffer from Uint8Array + bb = new ByteBuffer(0, littleEndian, noAssert); + if (buffer.length > 0) { // Avoid references to more than one EMPTY_BUFFER + bb.buffer = buffer.buffer; + bb.offset = buffer.byteOffset; + bb.limit = buffer.byteOffset + buffer.byteLength; + bb.view = new Uint8Array(buffer.buffer); + } + } else if (buffer instanceof ArrayBuffer) { // Reuse ArrayBuffer + bb = new ByteBuffer(0, littleEndian, noAssert); + if (buffer.byteLength > 0) { + bb.buffer = buffer; + bb.offset = 0; + bb.limit = buffer.byteLength; + bb.view = buffer.byteLength > 0 ? new Uint8Array(buffer) : null; + } + } else if (Object.prototype.toString.call(buffer) === "[object Array]") { // Create from octets + bb = new ByteBuffer(buffer.length, littleEndian, noAssert); + bb.limit = buffer.length; + for (var i=0; i} value Array of booleans to write + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ + ByteBufferPrototype.writeBitSet = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (!(value instanceof Array)) + throw TypeError("Illegal BitSet: Not an array"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + + var start = offset, + bits = value.length, + bytes = (bits >> 3), + bit = 0, + k; + + offset += this.writeVarint32(bits,offset); + + while(bytes--) { + k = (!!value[bit++] & 1) | + ((!!value[bit++] & 1) << 1) | + ((!!value[bit++] & 1) << 2) | + ((!!value[bit++] & 1) << 3) | + ((!!value[bit++] & 1) << 4) | + ((!!value[bit++] & 1) << 5) | + ((!!value[bit++] & 1) << 6) | + ((!!value[bit++] & 1) << 7); + this.writeByte(k,offset++); + } + + if(bit < bits) { + var m = 0; k = 0; + while(bit < bits) k = k | ((!!value[bit++] & 1) << (m++)); + this.writeByte(k,offset++); + } + + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + } + + /** + * Reads a BitSet as an array of booleans. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {Array + * @expose + */ + ByteBufferPrototype.readBitSet = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + + var ret = this.readVarint32(offset), + bits = ret.value, + bytes = (bits >> 3), + bit = 0, + value = [], + k; + + offset += ret.length; + + while(bytes--) { + k = this.readByte(offset++); + value[bit++] = !!(k & 0x01); + value[bit++] = !!(k & 0x02); + value[bit++] = !!(k & 0x04); + value[bit++] = !!(k & 0x08); + value[bit++] = !!(k & 0x10); + value[bit++] = !!(k & 0x20); + value[bit++] = !!(k & 0x40); + value[bit++] = !!(k & 0x80); + } + + if(bit < bits) { + var m = 0; + k = this.readByte(offset++); + while(bit < bits) value[bit++] = !!((k >> (m++)) & 1); + } + + if (relative) { + this.offset = offset; + } + return value; + } + /** + * Reads the specified number of bytes. + * @param {number} length Number of bytes to read + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `length` if omitted. + * @returns {!ByteBuffer} + * @expose + */ + ByteBufferPrototype.readBytes = function(length, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + length > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength); + } + var slice = this.slice(offset, offset + length); + if (relative) this.offset += length; + return slice; + }; + + /** + * Writes a payload of bytes. This is an alias of {@link ByteBuffer#append}. + * @function + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to write. If `source` is a ByteBuffer, its offsets + * will be modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeBytes = ByteBufferPrototype.append; + + // types/ints/int8 + + /** + * Writes an 8bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt8 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 1; + var capacity0 = this.buffer.byteLength; + if (offset > capacity0) + this.resize((capacity0 *= 2) > offset ? capacity0 : offset); + offset -= 1; + this.view[offset] = value; + if (relative) this.offset += 1; + return this; + }; + + /** + * Writes an 8bit signed integer. This is an alias of {@link ByteBuffer#writeInt8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeByte = ByteBufferPrototype.writeInt8; + + /** + * Reads an 8bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt8 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var value = this.view[offset]; + if ((value & 0x80) === 0x80) value = -(0xFF - value + 1); // Cast to signed + if (relative) this.offset += 1; + return value; + }; + + /** + * Reads an 8bit signed integer. This is an alias of {@link ByteBuffer#readInt8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readByte = ByteBufferPrototype.readInt8; + + /** + * Writes an 8bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint8 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 1; + var capacity1 = this.buffer.byteLength; + if (offset > capacity1) + this.resize((capacity1 *= 2) > offset ? capacity1 : offset); + offset -= 1; + this.view[offset] = value; + if (relative) this.offset += 1; + return this; + }; + + /** + * Writes an 8bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint8}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt8 = ByteBufferPrototype.writeUint8; + + /** + * Reads an 8bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUint8 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var value = this.view[offset]; + if (relative) this.offset += 1; + return value; + }; + + /** + * Reads an 8bit unsigned integer. This is an alias of {@link ByteBuffer#readUint8}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `1` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUInt8 = ByteBufferPrototype.readUint8; + + // types/ints/int16 + + /** + * Writes a 16bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeInt16 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 2; + var capacity2 = this.buffer.byteLength; + if (offset > capacity2) + this.resize((capacity2 *= 2) > offset ? capacity2 : offset); + offset -= 2; + if (this.littleEndian) { + this.view[offset+1] = (value & 0xFF00) >>> 8; + this.view[offset ] = value & 0x00FF; + } else { + this.view[offset] = (value & 0xFF00) >>> 8; + this.view[offset+1] = value & 0x00FF; + } + if (relative) this.offset += 2; + return this; + }; + + /** + * Writes a 16bit signed integer. This is an alias of {@link ByteBuffer#writeInt16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeShort = ByteBufferPrototype.writeInt16; + + /** + * Reads a 16bit signed integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readInt16 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 2 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength); + } + var value = 0; + if (this.littleEndian) { + value = this.view[offset ]; + value |= this.view[offset+1] << 8; + } else { + value = this.view[offset ] << 8; + value |= this.view[offset+1]; + } + if ((value & 0x8000) === 0x8000) value = -(0xFFFF - value + 1); // Cast to signed + if (relative) this.offset += 2; + return value; + }; + + /** + * Reads a 16bit signed integer. This is an alias of {@link ByteBuffer#readInt16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readShort = ByteBufferPrototype.readInt16; + + /** + * Writes a 16bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeUint16 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 2; + var capacity3 = this.buffer.byteLength; + if (offset > capacity3) + this.resize((capacity3 *= 2) > offset ? capacity3 : offset); + offset -= 2; + if (this.littleEndian) { + this.view[offset+1] = (value & 0xFF00) >>> 8; + this.view[offset ] = value & 0x00FF; + } else { + this.view[offset] = (value & 0xFF00) >>> 8; + this.view[offset+1] = value & 0x00FF; + } + if (relative) this.offset += 2; + return this; + }; + + /** + * Writes a 16bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint16}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @throws {TypeError} If `offset` or `value` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.writeUInt16 = ByteBufferPrototype.writeUint16; + + /** + * Reads a 16bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readUint16 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 2 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+2+") <= "+this.buffer.byteLength); + } + var value = 0; + if (this.littleEndian) { + value = this.view[offset ]; + value |= this.view[offset+1] << 8; + } else { + value = this.view[offset ] << 8; + value |= this.view[offset+1]; + } + if (relative) this.offset += 2; + return value; + }; + + /** + * Reads a 16bit unsigned integer. This is an alias of {@link ByteBuffer#readUint16}. + * @function + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `2` if omitted. + * @returns {number} Value read + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @expose + */ + ByteBufferPrototype.readUInt16 = ByteBufferPrototype.readUint16; + + // types/ints/int32 + + /** + * Writes a 32bit signed integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeInt32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity4 = this.buffer.byteLength; + if (offset > capacity4) + this.resize((capacity4 *= 2) > offset ? capacity4 : offset); + offset -= 4; + if (this.littleEndian) { + this.view[offset+3] = (value >>> 24) & 0xFF; + this.view[offset+2] = (value >>> 16) & 0xFF; + this.view[offset+1] = (value >>> 8) & 0xFF; + this.view[offset ] = value & 0xFF; + } else { + this.view[offset ] = (value >>> 24) & 0xFF; + this.view[offset+1] = (value >>> 16) & 0xFF; + this.view[offset+2] = (value >>> 8) & 0xFF; + this.view[offset+3] = value & 0xFF; + } + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit signed integer. This is an alias of {@link ByteBuffer#writeInt32}. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeInt = ByteBufferPrototype.writeInt32; + + /** + * Reads a 32bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = 0; + if (this.littleEndian) { + value = this.view[offset+2] << 16; + value |= this.view[offset+1] << 8; + value |= this.view[offset ]; + value += this.view[offset+3] << 24 >>> 0; + } else { + value = this.view[offset+1] << 16; + value |= this.view[offset+2] << 8; + value |= this.view[offset+3]; + value += this.view[offset ] << 24 >>> 0; + } + value |= 0; // Cast to signed + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit signed integer. This is an alias of {@link ByteBuffer#readInt32}. + * @param {number=} offset Offset to read from. Will use and advance {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readInt = ByteBufferPrototype.readInt32; + + /** + * Writes a 32bit unsigned integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeUint32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value >>>= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity5 = this.buffer.byteLength; + if (offset > capacity5) + this.resize((capacity5 *= 2) > offset ? capacity5 : offset); + offset -= 4; + if (this.littleEndian) { + this.view[offset+3] = (value >>> 24) & 0xFF; + this.view[offset+2] = (value >>> 16) & 0xFF; + this.view[offset+1] = (value >>> 8) & 0xFF; + this.view[offset ] = value & 0xFF; + } else { + this.view[offset ] = (value >>> 24) & 0xFF; + this.view[offset+1] = (value >>> 16) & 0xFF; + this.view[offset+2] = (value >>> 8) & 0xFF; + this.view[offset+3] = value & 0xFF; + } + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @expose + */ + ByteBufferPrototype.writeUInt32 = ByteBufferPrototype.writeUint32; + + /** + * Reads a 32bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUint32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = 0; + if (this.littleEndian) { + value = this.view[offset+2] << 16; + value |= this.view[offset+1] << 8; + value |= this.view[offset ]; + value += this.view[offset+3] << 24 >>> 0; + } else { + value = this.view[offset+1] << 16; + value |= this.view[offset+2] << 8; + value |= this.view[offset+3]; + value += this.view[offset ] << 24 >>> 0; + } + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit unsigned integer. This is an alias of {@link ByteBuffer#readUint32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} Value read + * @expose + */ + ByteBufferPrototype.readUInt32 = ByteBufferPrototype.readUint32; + + // types/ints/int64 + + if (Long) { + + /** + * Writes a 64bit signed integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeInt64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + offset += 8; + var capacity6 = this.buffer.byteLength; + if (offset > capacity6) + this.resize((capacity6 *= 2) > offset ? capacity6 : offset); + offset -= 8; + var lo = value.low, + hi = value.high; + if (this.littleEndian) { + this.view[offset+3] = (lo >>> 24) & 0xFF; + this.view[offset+2] = (lo >>> 16) & 0xFF; + this.view[offset+1] = (lo >>> 8) & 0xFF; + this.view[offset ] = lo & 0xFF; + offset += 4; + this.view[offset+3] = (hi >>> 24) & 0xFF; + this.view[offset+2] = (hi >>> 16) & 0xFF; + this.view[offset+1] = (hi >>> 8) & 0xFF; + this.view[offset ] = hi & 0xFF; + } else { + this.view[offset ] = (hi >>> 24) & 0xFF; + this.view[offset+1] = (hi >>> 16) & 0xFF; + this.view[offset+2] = (hi >>> 8) & 0xFF; + this.view[offset+3] = hi & 0xFF; + offset += 4; + this.view[offset ] = (lo >>> 24) & 0xFF; + this.view[offset+1] = (lo >>> 16) & 0xFF; + this.view[offset+2] = (lo >>> 8) & 0xFF; + this.view[offset+3] = lo & 0xFF; + } + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit signed integer. This is an alias of {@link ByteBuffer#writeInt64}. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeLong = ByteBufferPrototype.writeInt64; + + /** + * Reads a 64bit signed integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readInt64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var lo = 0, + hi = 0; + if (this.littleEndian) { + lo = this.view[offset+2] << 16; + lo |= this.view[offset+1] << 8; + lo |= this.view[offset ]; + lo += this.view[offset+3] << 24 >>> 0; + offset += 4; + hi = this.view[offset+2] << 16; + hi |= this.view[offset+1] << 8; + hi |= this.view[offset ]; + hi += this.view[offset+3] << 24 >>> 0; + } else { + hi = this.view[offset+1] << 16; + hi |= this.view[offset+2] << 8; + hi |= this.view[offset+3]; + hi += this.view[offset ] << 24 >>> 0; + offset += 4; + lo = this.view[offset+1] << 16; + lo |= this.view[offset+2] << 8; + lo |= this.view[offset+3]; + lo += this.view[offset ] << 24 >>> 0; + } + var value = new Long(lo, hi, false); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit signed integer. This is an alias of {@link ByteBuffer#readInt64}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readLong = ByteBufferPrototype.readInt64; + + /** + * Writes a 64bit unsigned integer. + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUint64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + offset += 8; + var capacity7 = this.buffer.byteLength; + if (offset > capacity7) + this.resize((capacity7 *= 2) > offset ? capacity7 : offset); + offset -= 8; + var lo = value.low, + hi = value.high; + if (this.littleEndian) { + this.view[offset+3] = (lo >>> 24) & 0xFF; + this.view[offset+2] = (lo >>> 16) & 0xFF; + this.view[offset+1] = (lo >>> 8) & 0xFF; + this.view[offset ] = lo & 0xFF; + offset += 4; + this.view[offset+3] = (hi >>> 24) & 0xFF; + this.view[offset+2] = (hi >>> 16) & 0xFF; + this.view[offset+1] = (hi >>> 8) & 0xFF; + this.view[offset ] = hi & 0xFF; + } else { + this.view[offset ] = (hi >>> 24) & 0xFF; + this.view[offset+1] = (hi >>> 16) & 0xFF; + this.view[offset+2] = (hi >>> 8) & 0xFF; + this.view[offset+3] = hi & 0xFF; + offset += 4; + this.view[offset ] = (lo >>> 24) & 0xFF; + this.view[offset+1] = (lo >>> 16) & 0xFF; + this.view[offset+2] = (lo >>> 8) & 0xFF; + this.view[offset+3] = lo & 0xFF; + } + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit unsigned integer. This is an alias of {@link ByteBuffer#writeUint64}. + * @function + * @param {number|!Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeUInt64 = ByteBufferPrototype.writeUint64; + + /** + * Reads a 64bit unsigned integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUint64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var lo = 0, + hi = 0; + if (this.littleEndian) { + lo = this.view[offset+2] << 16; + lo |= this.view[offset+1] << 8; + lo |= this.view[offset ]; + lo += this.view[offset+3] << 24 >>> 0; + offset += 4; + hi = this.view[offset+2] << 16; + hi |= this.view[offset+1] << 8; + hi |= this.view[offset ]; + hi += this.view[offset+3] << 24 >>> 0; + } else { + hi = this.view[offset+1] << 16; + hi |= this.view[offset+2] << 8; + hi |= this.view[offset+3]; + hi += this.view[offset ] << 24 >>> 0; + offset += 4; + lo = this.view[offset+1] << 16; + lo |= this.view[offset+2] << 8; + lo |= this.view[offset+3]; + lo += this.view[offset ] << 24 >>> 0; + } + var value = new Long(lo, hi, true); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit unsigned integer. This is an alias of {@link ByteBuffer#readUint64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!Long} + * @expose + */ + ByteBufferPrototype.readUInt64 = ByteBufferPrototype.readUint64; + + } // Long + + + // types/floats/float32 + + /* + ieee754 - https://github.com/feross/ieee754 + + The MIT License (MIT) + + Copyright (c) Feross Aboukhadijeh + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ + + /** + * Reads an IEEE754 float from a byte array. + * @param {!Array} buffer + * @param {number} offset + * @param {boolean} isLE + * @param {number} mLen + * @param {number} nBytes + * @returns {number} + * @inner + */ + function ieee754_read(buffer, offset, isLE, mLen, nBytes) { + var e, m, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + nBits = -7, + i = isLE ? (nBytes - 1) : 0, + d = isLE ? -1 : 1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); + } + + /** + * Writes an IEEE754 float to a byte array. + * @param {!Array} buffer + * @param {number} value + * @param {number} offset + * @param {boolean} isLE + * @param {number} mLen + * @param {number} nBytes + * @inner + */ + function ieee754_write(buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = isLE ? 0 : (nBytes - 1), + d = isLE ? 1 : -1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128; + } + + /** + * Writes a 32bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 4; + var capacity8 = this.buffer.byteLength; + if (offset > capacity8) + this.resize((capacity8 *= 2) > offset ? capacity8 : offset); + offset -= 4; + ieee754_write(this.view, value, offset, this.littleEndian, 23, 4); + if (relative) this.offset += 4; + return this; + }; + + /** + * Writes a 32bit float. This is an alias of {@link ByteBuffer#writeFloat32}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat = ByteBufferPrototype.writeFloat32; + + /** + * Reads a 32bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var value = ieee754_read(this.view, offset, this.littleEndian, 23, 4); + if (relative) this.offset += 4; + return value; + }; + + /** + * Reads a 32bit float. This is an alias of {@link ByteBuffer#readFloat32}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `4` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat = ByteBufferPrototype.readFloat32; + + // types/floats/float64 + + /** + * Writes a 64bit float. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeFloat64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number') + throw TypeError("Illegal value: "+value+" (not a number)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + offset += 8; + var capacity9 = this.buffer.byteLength; + if (offset > capacity9) + this.resize((capacity9 *= 2) > offset ? capacity9 : offset); + offset -= 8; + ieee754_write(this.view, value, offset, this.littleEndian, 52, 8); + if (relative) this.offset += 8; + return this; + }; + + /** + * Writes a 64bit float. This is an alias of {@link ByteBuffer#writeFloat64}. + * @function + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.writeDouble = ByteBufferPrototype.writeFloat64; + + /** + * Reads a 64bit float. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readFloat64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 8 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+8+") <= "+this.buffer.byteLength); + } + var value = ieee754_read(this.view, offset, this.littleEndian, 52, 8); + if (relative) this.offset += 8; + return value; + }; + + /** + * Reads a 64bit float. This is an alias of {@link ByteBuffer#readFloat64}. + * @function + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by `8` if omitted. + * @returns {number} + * @expose + */ + ByteBufferPrototype.readDouble = ByteBufferPrototype.readFloat64; + + + // types/varints/varint32 + + /** + * Maximum number of bytes required to store a 32bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT32_BYTES = 5; + + /** + * Calculates the actual number of bytes required to store a 32bit base 128 variable-length integer. + * @param {number} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT32_BYTES} + * @expose + */ + ByteBuffer.calculateVarint32 = function(value) { + // ref: src/google/protobuf/io/coded_stream.cc + value = value >>> 0; + if (value < 1 << 7 ) return 1; + else if (value < 1 << 14) return 2; + else if (value < 1 << 21) return 3; + else if (value < 1 << 28) return 4; + else return 5; + }; + + /** + * Zigzag encodes a signed 32bit integer so that it can be effectively used with varint encoding. + * @param {number} n Signed 32bit integer + * @returns {number} Unsigned zigzag encoded 32bit integer + * @expose + */ + ByteBuffer.zigZagEncode32 = function(n) { + return (((n |= 0) << 1) ^ (n >> 31)) >>> 0; // ref: src/google/protobuf/wire_format_lite.h + }; + + /** + * Decodes a zigzag encoded signed 32bit integer. + * @param {number} n Unsigned zigzag encoded 32bit integer + * @returns {number} Signed 32bit integer + * @expose + */ + ByteBuffer.zigZagDecode32 = function(n) { + return ((n >>> 1) ^ -(n & 1)) | 0; // // ref: src/google/protobuf/wire_format_lite.h + }; + + /** + * Writes a 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeVarint32 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var size = ByteBuffer.calculateVarint32(value), + b; + offset += size; + var capacity10 = this.buffer.byteLength; + if (offset > capacity10) + this.resize((capacity10 *= 2) > offset ? capacity10 : offset); + offset -= size; + value >>>= 0; + while (value >= 0x80) { + b = (value & 0x7f) | 0x80; + this.view[offset++] = b; + value >>>= 7; + } + this.view[offset++] = value; + if (relative) { + this.offset = offset; + return this; + } + return size; + }; + + /** + * Writes a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} this if `offset` is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeVarint32ZigZag = function(value, offset) { + return this.writeVarint32(ByteBuffer.zigZagEncode32(value), offset); + }; + + /** + * Reads a 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint. Has a property `truncated = true` if there is not enough data available + * to fully decode the varint. + * @expose + */ + ByteBufferPrototype.readVarint32 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var c = 0, + value = 0 >>> 0, + b; + do { + if (!this.noAssert && offset > this.limit) { + var err = Error("Truncated"); + err['truncated'] = true; + throw err; + } + b = this.view[offset++]; + if (c < 5) + value |= (b & 0x7f) << (7*c); + ++c; + } while ((b & 0x80) !== 0); + value |= 0; + if (relative) { + this.offset = offset; + return value; + } + return { + "value": value, + "length": c + }; + }; + + /** + * Reads a zig-zag encoded (signed) 32bit base 128 variable-length integer. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {number|!{value: number, length: number}} The value read if offset is omitted, else the value read + * and the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint32ZigZag = function(offset) { + var val = this.readVarint32(offset); + if (typeof val === 'object') + val["value"] = ByteBuffer.zigZagDecode32(val["value"]); + else + val = ByteBuffer.zigZagDecode32(val); + return val; + }; + + // types/varints/varint64 + + if (Long) { + + /** + * Maximum number of bytes required to store a 64bit base 128 variable-length integer. + * @type {number} + * @const + * @expose + */ + ByteBuffer.MAX_VARINT64_BYTES = 10; + + /** + * Calculates the actual number of bytes required to store a 64bit base 128 variable-length integer. + * @param {number|!Long} value Value to encode + * @returns {number} Number of bytes required. Capped to {@link ByteBuffer.MAX_VARINT64_BYTES} + * @expose + */ + ByteBuffer.calculateVarint64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + // ref: src/google/protobuf/io/coded_stream.cc + var part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + if (part2 == 0) { + if (part1 == 0) { + if (part0 < 1 << 14) + return part0 < 1 << 7 ? 1 : 2; + else + return part0 < 1 << 21 ? 3 : 4; + } else { + if (part1 < 1 << 14) + return part1 < 1 << 7 ? 5 : 6; + else + return part1 < 1 << 21 ? 7 : 8; + } + } else + return part2 < 1 << 7 ? 9 : 10; + }; + + /** + * Zigzag encodes a signed 64bit integer so that it can be effectively used with varint encoding. + * @param {number|!Long} value Signed long + * @returns {!Long} Unsigned zigzag encoded long + * @expose + */ + ByteBuffer.zigZagEncode64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftLeft(1).xor(value.shiftRight(63)).toUnsigned(); + }; + + /** + * Decodes a zigzag encoded signed 64bit integer. + * @param {!Long|number} value Unsigned zigzag encoded long or JavaScript number + * @returns {!Long} Signed long + * @expose + */ + ByteBuffer.zigZagDecode64 = function(value) { + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + // ref: src/google/protobuf/wire_format_lite.h + return value.shiftRightUnsigned(1).xor(value.and(Long.ONE).toSigned().negate()).toSigned(); + }; + + /** + * Writes a 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64 = function(value, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof value === 'number') + value = Long.fromNumber(value); + else if (typeof value === 'string') + value = Long.fromString(value); + else if (!(value && value instanceof Long)) + throw TypeError("Illegal value: "+value+" (not an integer or Long)"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (typeof value === 'number') + value = Long.fromNumber(value, false); + else if (typeof value === 'string') + value = Long.fromString(value, false); + else if (value.unsigned !== false) value = value.toSigned(); + var size = ByteBuffer.calculateVarint64(value), + part0 = value.toInt() >>> 0, + part1 = value.shiftRightUnsigned(28).toInt() >>> 0, + part2 = value.shiftRightUnsigned(56).toInt() >>> 0; + offset += size; + var capacity11 = this.buffer.byteLength; + if (offset > capacity11) + this.resize((capacity11 *= 2) > offset ? capacity11 : offset); + offset -= size; + switch (size) { + case 10: this.view[offset+9] = (part2 >>> 7) & 0x01; + case 9 : this.view[offset+8] = size !== 9 ? (part2 ) | 0x80 : (part2 ) & 0x7F; + case 8 : this.view[offset+7] = size !== 8 ? (part1 >>> 21) | 0x80 : (part1 >>> 21) & 0x7F; + case 7 : this.view[offset+6] = size !== 7 ? (part1 >>> 14) | 0x80 : (part1 >>> 14) & 0x7F; + case 6 : this.view[offset+5] = size !== 6 ? (part1 >>> 7) | 0x80 : (part1 >>> 7) & 0x7F; + case 5 : this.view[offset+4] = size !== 5 ? (part1 ) | 0x80 : (part1 ) & 0x7F; + case 4 : this.view[offset+3] = size !== 4 ? (part0 >>> 21) | 0x80 : (part0 >>> 21) & 0x7F; + case 3 : this.view[offset+2] = size !== 3 ? (part0 >>> 14) | 0x80 : (part0 >>> 14) & 0x7F; + case 2 : this.view[offset+1] = size !== 2 ? (part0 >>> 7) | 0x80 : (part0 >>> 7) & 0x7F; + case 1 : this.view[offset ] = size !== 1 ? (part0 ) | 0x80 : (part0 ) & 0x7F; + } + if (relative) { + this.offset += size; + return this; + } else { + return size; + } + }; + + /** + * Writes a zig-zag encoded 64bit base 128 variable-length integer. + * @param {number|Long} value Value to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeVarint64ZigZag = function(value, offset) { + return this.writeVarint64(ByteBuffer.zigZagEncode64(value), offset); + }; + + /** + * Reads a 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64 = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + // ref: src/google/protobuf/io/coded_stream.cc + var start = offset, + part0 = 0, + part1 = 0, + part2 = 0, + b = 0; + b = this.view[offset++]; part0 = (b & 0x7F) ; if ( b & 0x80 ) { + b = this.view[offset++]; part0 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part0 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part0 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part1 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part1 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part1 |= (b & 0x7F) << 14; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part1 |= (b & 0x7F) << 21; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part2 = (b & 0x7F) ; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + b = this.view[offset++]; part2 |= (b & 0x7F) << 7; if ((b & 0x80) || (this.noAssert && typeof b === 'undefined')) { + throw Error("Buffer overrun"); }}}}}}}}}} + var value = Long.fromBits(part0 | (part1 << 28), (part1 >>> 4) | (part2) << 24, false); + if (relative) { + this.offset = offset; + return value; + } else { + return { + 'value': value, + 'length': offset-start + }; + } + }; + + /** + * Reads a zig-zag encoded 64bit base 128 variable-length integer. Requires Long.js. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!Long|!{value: Long, length: number}} The value read if offset is omitted, else the value read and + * the actual number of bytes read. + * @throws {Error} If it's not a valid varint + * @expose + */ + ByteBufferPrototype.readVarint64ZigZag = function(offset) { + var val = this.readVarint64(offset); + if (val && val['value'] instanceof Long) + val["value"] = ByteBuffer.zigZagDecode64(val["value"]); + else + val = ByteBuffer.zigZagDecode64(val); + return val; + }; + + } // Long + + + // types/strings/cstring + + /** + * Writes a NULL-terminated UTF8 encoded string. For this to work the specified string must not contain any NULL + * characters itself. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * contained in `str` + 1 if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written + * @expose + */ + ByteBufferPrototype.writeCString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + var i, + k = str.length; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + for (i=0; i>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + // UTF8 strings do not contain zero bytes in between except for the zero character, so: + k = utfx.calculateUTF16asUTF8(stringSource(str))[1]; + offset += k+1; + var capacity12 = this.buffer.byteLength; + if (offset > capacity12) + this.resize((capacity12 *= 2) > offset ? capacity12 : offset); + offset -= k+1; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view[offset++] = b; + }.bind(this)); + this.view[offset++] = 0; + if (relative) { + this.offset = offset; + return this; + } + return k; + }; + + /** + * Reads a NULL-terminated UTF8 encoded string. For this to work the string read must not contain any NULL characters + * itself. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readCString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var start = offset, + temp; + // UTF8 strings do not contain zero bytes in between except for the zero character itself, so: + var sd, b = -1; + utfx.decodeUTF8toUTF16(function() { + if (b === 0) return null; + if (offset >= this.limit) + throw RangeError("Illegal range: Truncated data, "+offset+" < "+this.limit); + b = this.view[offset++]; + return b === 0 ? null : b; + }.bind(this), sd = stringDestination(), true); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + }; + + // types/strings/istring + + /** + * Writes a length as uint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ + ByteBufferPrototype.writeIString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var start = offset, + k; + k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1]; + offset += 4+k; + var capacity13 = this.buffer.byteLength; + if (offset > capacity13) + this.resize((capacity13 *= 2) > offset ? capacity13 : offset); + offset -= 4+k; + if (this.littleEndian) { + this.view[offset+3] = (k >>> 24) & 0xFF; + this.view[offset+2] = (k >>> 16) & 0xFF; + this.view[offset+1] = (k >>> 8) & 0xFF; + this.view[offset ] = k & 0xFF; + } else { + this.view[offset ] = (k >>> 24) & 0xFF; + this.view[offset+1] = (k >>> 16) & 0xFF; + this.view[offset+2] = (k >>> 8) & 0xFF; + this.view[offset+3] = k & 0xFF; + } + offset += 4; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view[offset++] = b; + }.bind(this)); + if (offset !== start + 4 + k) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+4+k)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Reads a length as uint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ + ByteBufferPrototype.readIString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 4 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+4+") <= "+this.buffer.byteLength); + } + var start = offset; + var len = this.readUint32(offset); + var str = this.readUTF8String(len, ByteBuffer.METRICS_BYTES, offset += 4); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } + }; + + // types/strings/utf8string + + /** + * Metrics representing number of UTF8 characters. Evaluates to `c`. + * @type {string} + * @const + * @expose + */ + ByteBuffer.METRICS_CHARS = 'c'; + + /** + * Metrics representing number of bytes. Evaluates to `b`. + * @type {string} + * @const + * @expose + */ + ByteBuffer.METRICS_BYTES = 'b'; + + /** + * Writes an UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeUTF8String = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var k; + var start = offset; + k = utfx.calculateUTF16asUTF8(stringSource(str))[1]; + offset += k; + var capacity14 = this.buffer.byteLength; + if (offset > capacity14) + this.resize((capacity14 *= 2) > offset ? capacity14 : offset); + offset -= k; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view[offset++] = b; + }.bind(this)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Writes an UTF8 encoded string. This is an alias of {@link ByteBuffer#writeUTF8String}. + * @function + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} if omitted. + * @returns {!ByteBuffer|number} this if offset is omitted, else the actual number of bytes written. + * @expose + */ + ByteBufferPrototype.writeString = ByteBufferPrototype.writeUTF8String; + + /** + * Calculates the number of UTF8 characters of a string. JavaScript itself uses UTF-16, so that a string's + * `length` property does not reflect its actual UTF8 size if it contains code points larger than 0xFFFF. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 characters + * @expose + */ + ByteBuffer.calculateUTF8Chars = function(str) { + return utfx.calculateUTF16asUTF8(stringSource(str))[0]; + }; + + /** + * Calculates the number of UTF8 bytes of a string. + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ + ByteBuffer.calculateUTF8Bytes = function(str) { + return utfx.calculateUTF16asUTF8(stringSource(str))[1]; + }; + + /** + * Calculates the number of UTF8 bytes of a string. This is an alias of {@link ByteBuffer.calculateUTF8Bytes}. + * @function + * @param {string} str String to calculate + * @returns {number} Number of UTF8 bytes + * @expose + */ + ByteBuffer.calculateString = ByteBuffer.calculateUTF8Bytes; + + /** + * Reads an UTF8 encoded string. + * @param {number} length Number of characters or bytes to read. + * @param {string=} metrics Metrics specifying what `length` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readUTF8String = function(length, metrics, offset) { + if (typeof metrics === 'number') { + offset = metrics; + metrics = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (typeof metrics === 'undefined') metrics = ByteBuffer.METRICS_CHARS; + if (!this.noAssert) { + if (typeof length !== 'number' || length % 1 !== 0) + throw TypeError("Illegal length: "+length+" (not an integer)"); + length |= 0; + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var i = 0, + start = offset, + sd; + if (metrics === ByteBuffer.METRICS_CHARS) { // The same for node and the browser + sd = stringDestination(); + utfx.decodeUTF8(function() { + return i < length && offset < this.limit ? this.view[offset++] : null; + }.bind(this), function(cp) { + ++i; utfx.UTF8toUTF16(cp, sd); + }); + if (i !== length) + throw RangeError("Illegal range: Truncated data, "+i+" == "+length); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + "string": sd(), + "length": offset - start + }; + } + } else if (metrics === ByteBuffer.METRICS_BYTES) { + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + length > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+length+") <= "+this.buffer.byteLength); + } + var k = offset + length; + utfx.decodeUTF8toUTF16(function() { + return offset < k ? this.view[offset++] : null; + }.bind(this), sd = stringDestination(), this.noAssert); + if (offset !== k) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+k); + if (relative) { + this.offset = offset; + return sd(); + } else { + return { + 'string': sd(), + 'length': offset - start + }; + } + } else + throw TypeError("Unsupported metrics: "+metrics); + }; + + /** + * Reads an UTF8 encoded string. This is an alias of {@link ByteBuffer#readUTF8String}. + * @function + * @param {number} length Number of characters or bytes to read + * @param {number=} metrics Metrics specifying what `n` is meant to count. Defaults to + * {@link ByteBuffer.METRICS_CHARS}. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + */ + ByteBufferPrototype.readString = ByteBufferPrototype.readUTF8String; + + // types/strings/vstring + + /** + * Writes a length as varint32 prefixed UTF8 encoded string. + * @param {string} str String to write + * @param {number=} offset Offset to write to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer|number} `this` if `offset` is omitted, else the actual number of bytes written + * @expose + * @see ByteBuffer#writeVarint32 + */ + ByteBufferPrototype.writeVString = function(str, offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + var start = offset, + k, l; + k = utfx.calculateUTF16asUTF8(stringSource(str), this.noAssert)[1]; + l = ByteBuffer.calculateVarint32(k); + offset += l+k; + var capacity15 = this.buffer.byteLength; + if (offset > capacity15) + this.resize((capacity15 *= 2) > offset ? capacity15 : offset); + offset -= l+k; + offset += this.writeVarint32(k, offset); + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + this.view[offset++] = b; + }.bind(this)); + if (offset !== start+k+l) + throw RangeError("Illegal range: Truncated data, "+offset+" == "+(offset+k+l)); + if (relative) { + this.offset = offset; + return this; + } + return offset - start; + }; + + /** + * Reads a length as varint32 prefixed UTF8 encoded string. + * @param {number=} offset Offset to read from. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {string|!{string: string, length: number}} The string read if offset is omitted, else the string + * read and the actual number of bytes read. + * @expose + * @see ByteBuffer#readVarint32 + */ + ByteBufferPrototype.readVString = function(offset) { + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 1 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+1+") <= "+this.buffer.byteLength); + } + var start = offset; + var len = this.readVarint32(offset); + var str = this.readUTF8String(len['value'], ByteBuffer.METRICS_BYTES, offset += len['length']); + offset += str['length']; + if (relative) { + this.offset = offset; + return str['string']; + } else { + return { + 'string': str['string'], + 'length': offset - start + }; + } + }; + + + /** + * Appends some data to this ByteBuffer. This will overwrite any contents behind the specified offset up to the appended + * data's length. + * @param {!ByteBuffer|!ArrayBuffer|!Uint8Array|string} source Data to append. If `source` is a ByteBuffer, its offsets + * will be modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to append at. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `<01 02>03.append(<04 05>)` will result in `<01 02 04 05>, 04 05|` + * @example An absolute `<01 02>03.append(04 05>, 1)` will result in `<01 04>05, 04 05|` + */ + ByteBufferPrototype.append = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var length = source.limit - source.offset; + if (length <= 0) return this; // Nothing to append + offset += length; + var capacity16 = this.buffer.byteLength; + if (offset > capacity16) + this.resize((capacity16 *= 2) > offset ? capacity16 : offset); + offset -= length; + this.view.set(source.view.subarray(source.offset, source.limit), offset); + source.offset += length; + if (relative) this.offset += length; + return this; + }; + + /** + * Appends this ByteBuffer's contents to another ByteBuffer. This will overwrite any contents at and after the + specified offset up to the length of this ByteBuffer's data. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to append to. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * read if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#append + */ + ByteBufferPrototype.appendTo = function(target, offset) { + target.append(this, offset); + return this; + }; + + /** + * Enables or disables assertions of argument types and offsets. Assertions are enabled by default but you can opt to + * disable them if your code already makes sure that everything is valid. + * @param {boolean} assert `true` to enable assertions, otherwise `false` + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.assert = function(assert) { + this.noAssert = !assert; + return this; + }; + + /** + * Gets the capacity of this ByteBuffer's backing buffer. + * @returns {number} Capacity of the backing buffer + * @expose + */ + ByteBufferPrototype.capacity = function() { + return this.buffer.byteLength; + }; + /** + * Clears this ByteBuffer's offsets by setting {@link ByteBuffer#offset} to `0` and {@link ByteBuffer#limit} to the + * backing buffer's capacity. Discards {@link ByteBuffer#markedOffset}. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.clear = function() { + this.offset = 0; + this.limit = this.buffer.byteLength; + this.markedOffset = -1; + return this; + }; + + /** + * Creates a cloned instance of this ByteBuffer, preset with this ByteBuffer's values for {@link ByteBuffer#offset}, + * {@link ByteBuffer#markedOffset} and {@link ByteBuffer#limit}. + * @param {boolean=} copy Whether to copy the backing buffer or to return another view on the same, defaults to `false` + * @returns {!ByteBuffer} Cloned instance + * @expose + */ + ByteBufferPrototype.clone = function(copy) { + var bb = new ByteBuffer(0, this.littleEndian, this.noAssert); + if (copy) { + bb.buffer = new ArrayBuffer(this.buffer.byteLength); + bb.view = new Uint8Array(bb.buffer); + } else { + bb.buffer = this.buffer; + bb.view = this.view; + } + bb.offset = this.offset; + bb.markedOffset = this.markedOffset; + bb.limit = this.limit; + return bb; + }; + + /** + * Compacts this ByteBuffer to be backed by a {@link ByteBuffer#buffer} of its contents' length. Contents are the bytes + * between {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. Will set `offset = 0` and `limit = capacity` and + * adapt {@link ByteBuffer#markedOffset} to the same relative position if set. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.compact = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === 0 && end === this.buffer.byteLength) + return this; // Already compacted + var len = end - begin; + if (len === 0) { + this.buffer = EMPTY_BUFFER; + this.view = null; + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = 0; + return this; + } + var buffer = new ArrayBuffer(len); + var view = new Uint8Array(buffer); + view.set(this.view.subarray(begin, end)); + this.buffer = buffer; + this.view = view; + if (this.markedOffset >= 0) this.markedOffset -= begin; + this.offset = 0; + this.limit = len; + return this; + }; + + /** + * Creates a copy of this ByteBuffer's contents. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Copy + * @expose + */ + ByteBufferPrototype.copy = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === end) + return new ByteBuffer(0, this.littleEndian, this.noAssert); + var capacity = end - begin, + bb = new ByteBuffer(capacity, this.littleEndian, this.noAssert); + bb.offset = 0; + bb.limit = capacity; + if (bb.markedOffset >= 0) bb.markedOffset -= begin; + this.copyTo(bb, 0, begin, end); + return bb; + }; + + /** + * Copies this ByteBuffer's contents to another ByteBuffer. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} targetOffset Offset to copy to. Will use and increase the target's {@link ByteBuffer#offset} + * by the number of bytes copied if omitted. + * @param {number=} sourceOffset Offset to start copying from. Will use and increase {@link ByteBuffer#offset} by the + * number of bytes copied if omitted. + * @param {number=} sourceLimit Offset to end copying from, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.copyTo = function(target, targetOffset, sourceOffset, sourceLimit) { + var relative, + targetRelative; + if (!this.noAssert) { + if (!ByteBuffer.isByteBuffer(target)) + throw TypeError("Illegal target: Not a ByteBuffer"); + } + targetOffset = (targetRelative = typeof targetOffset === 'undefined') ? target.offset : targetOffset | 0; + sourceOffset = (relative = typeof sourceOffset === 'undefined') ? this.offset : sourceOffset | 0; + sourceLimit = typeof sourceLimit === 'undefined' ? this.limit : sourceLimit | 0; + + if (targetOffset < 0 || targetOffset > target.buffer.byteLength) + throw RangeError("Illegal target range: 0 <= "+targetOffset+" <= "+target.buffer.byteLength); + if (sourceOffset < 0 || sourceLimit > this.buffer.byteLength) + throw RangeError("Illegal source range: 0 <= "+sourceOffset+" <= "+this.buffer.byteLength); + + var len = sourceLimit - sourceOffset; + if (len === 0) + return target; // Nothing to copy + + target.ensureCapacity(targetOffset + len); + + target.view.set(this.view.subarray(sourceOffset, sourceLimit), targetOffset); + + if (relative) this.offset += len; + if (targetRelative) target.offset += len; + + return this; + }; + + /** + * Makes sure that this ByteBuffer is backed by a {@link ByteBuffer#buffer} of at least the specified capacity. If the + * current capacity is exceeded, it will be doubled. If double the current capacity is less than the required capacity, + * the required capacity will be used instead. + * @param {number} capacity Required capacity + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.ensureCapacity = function(capacity) { + var current = this.buffer.byteLength; + if (current < capacity) + return this.resize((current *= 2) > capacity ? current : capacity); + return this; + }; + + /** + * Overwrites this ByteBuffer's contents with the specified value. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {number|string} value Byte value to fill with. If given as a string, the first character is used. + * @param {number=} begin Begin offset. Will use and increase {@link ByteBuffer#offset} by the number of bytes + * written if omitted. defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} this + * @expose + * @example `someByteBuffer.clear().fill(0)` fills the entire backing buffer with zeroes + */ + ByteBufferPrototype.fill = function(value, begin, end) { + var relative = typeof begin === 'undefined'; + if (relative) begin = this.offset; + if (typeof value === 'string' && value.length > 0) + value = value.charCodeAt(0); + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof value !== 'number' || value % 1 !== 0) + throw TypeError("Illegal value: "+value+" (not an integer)"); + value |= 0; + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin >= end) + return this; // Nothing to fill + while (begin < end) this.view[begin++] = value; + if (relative) this.offset = begin; + return this; + }; + + /** + * Makes this ByteBuffer ready for a new sequence of write or relative read operations. Sets `limit = offset` and + * `offset = 0`. Make sure always to flip a ByteBuffer when all relative read or write operations are complete. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.flip = function() { + this.limit = this.offset; + this.offset = 0; + return this; + }; + /** + * Marks an offset on this ByteBuffer to be used later. + * @param {number=} offset Offset to mark. Defaults to {@link ByteBuffer#offset}. + * @returns {!ByteBuffer} this + * @throws {TypeError} If `offset` is not a valid number + * @throws {RangeError} If `offset` is out of bounds + * @see ByteBuffer#reset + * @expose + */ + ByteBufferPrototype.mark = function(offset) { + offset = typeof offset === 'undefined' ? this.offset : offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + this.markedOffset = offset; + return this; + }; + /** + * Sets the byte order. + * @param {boolean} littleEndian `true` for little endian byte order, `false` for big endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.order = function(littleEndian) { + if (!this.noAssert) { + if (typeof littleEndian !== 'boolean') + throw TypeError("Illegal littleEndian: Not a boolean"); + } + this.littleEndian = !!littleEndian; + return this; + }; + + /** + * Switches (to) little endian byte order. + * @param {boolean=} littleEndian Defaults to `true`, otherwise uses big endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.LE = function(littleEndian) { + this.littleEndian = typeof littleEndian !== 'undefined' ? !!littleEndian : true; + return this; + }; + + /** + * Switches (to) big endian byte order. + * @param {boolean=} bigEndian Defaults to `true`, otherwise uses little endian + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.BE = function(bigEndian) { + this.littleEndian = typeof bigEndian !== 'undefined' ? !bigEndian : false; + return this; + }; + /** + * Prepends some data to this ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer|string|!ArrayBuffer} source Data to prepend. If `source` is a ByteBuffer, its offset will be + * modified according to the performed read operation. + * @param {(string|number)=} encoding Encoding if `data` is a string ("base64", "hex", "binary", defaults to "utf8") + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @example A relative `00<01 02 03>.prepend(<04 05>)` results in `<04 05 01 02 03>, 04 05|` + * @example An absolute `00<01 02 03>.prepend(<04 05>, 2)` results in `04<05 02 03>, 04 05|` + */ + ByteBufferPrototype.prepend = function(source, encoding, offset) { + if (typeof encoding === 'number' || typeof encoding !== 'string') { + offset = encoding; + encoding = undefined; + } + var relative = typeof offset === 'undefined'; + if (relative) offset = this.offset; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: "+offset+" (not an integer)"); + offset >>>= 0; + if (offset < 0 || offset + 0 > this.buffer.byteLength) + throw RangeError("Illegal offset: 0 <= "+offset+" (+"+0+") <= "+this.buffer.byteLength); + } + if (!(source instanceof ByteBuffer)) + source = ByteBuffer.wrap(source, encoding); + var len = source.limit - source.offset; + if (len <= 0) return this; // Nothing to prepend + var diff = len - offset; + if (diff > 0) { // Not enough space before offset, so resize + move + var buffer = new ArrayBuffer(this.buffer.byteLength + diff); + var view = new Uint8Array(buffer); + view.set(this.view.subarray(offset, this.buffer.byteLength), len); + this.buffer = buffer; + this.view = view; + this.offset += diff; + if (this.markedOffset >= 0) this.markedOffset += diff; + this.limit += diff; + offset += diff; + } else { + var arrayView = new Uint8Array(this.buffer); + } + this.view.set(source.view.subarray(source.offset, source.limit), offset - len); + + source.offset = source.limit; + if (relative) + this.offset -= len; + return this; + }; + + /** + * Prepends this ByteBuffer to another ByteBuffer. This will overwrite any contents before the specified offset up to the + * prepended data's length. If there is not enough space available before the specified `offset`, the backing buffer + * will be resized and its contents moved accordingly. + * @param {!ByteBuffer} target Target ByteBuffer + * @param {number=} offset Offset to prepend at. Will use and decrease {@link ByteBuffer#offset} by the number of bytes + * prepended if omitted. + * @returns {!ByteBuffer} this + * @expose + * @see ByteBuffer#prepend + */ + ByteBufferPrototype.prependTo = function(target, offset) { + target.prepend(this, offset); + return this; + }; + /** + * Prints debug information about this ByteBuffer's contents. + * @param {function(string)=} out Output function to call, defaults to console.log + * @expose + */ + ByteBufferPrototype.printDebug = function(out) { + if (typeof out !== 'function') out = console.log.bind(console); + out( + this.toString()+"\n"+ + "-------------------------------------------------------------------\n"+ + this.toDebug(/* columns */ true) + ); + }; + + /** + * Gets the number of remaining readable bytes. Contents are the bytes between {@link ByteBuffer#offset} and + * {@link ByteBuffer#limit}, so this returns `limit - offset`. + * @returns {number} Remaining readable bytes. May be negative if `offset > limit`. + * @expose + */ + ByteBufferPrototype.remaining = function() { + return this.limit - this.offset; + }; + /** + * Resets this ByteBuffer's {@link ByteBuffer#offset}. If an offset has been marked through {@link ByteBuffer#mark} + * before, `offset` will be set to {@link ByteBuffer#markedOffset}, which will then be discarded. If no offset has been + * marked, sets `offset = 0`. + * @returns {!ByteBuffer} this + * @see ByteBuffer#mark + * @expose + */ + ByteBufferPrototype.reset = function() { + if (this.markedOffset >= 0) { + this.offset = this.markedOffset; + this.markedOffset = -1; + } else { + this.offset = 0; + } + return this; + }; + /** + * Resizes this ByteBuffer to be backed by a buffer of at least the given capacity. Will do nothing if already that + * large or larger. + * @param {number} capacity Capacity required + * @returns {!ByteBuffer} this + * @throws {TypeError} If `capacity` is not a number + * @throws {RangeError} If `capacity < 0` + * @expose + */ + ByteBufferPrototype.resize = function(capacity) { + if (!this.noAssert) { + if (typeof capacity !== 'number' || capacity % 1 !== 0) + throw TypeError("Illegal capacity: "+capacity+" (not an integer)"); + capacity |= 0; + if (capacity < 0) + throw RangeError("Illegal capacity: 0 <= "+capacity); + } + if (this.buffer.byteLength < capacity) { + var buffer = new ArrayBuffer(capacity); + var view = new Uint8Array(buffer); + view.set(this.view); + this.buffer = buffer; + this.view = view; + } + return this; + }; + /** + * Reverses this ByteBuffer's contents. + * @param {number=} begin Offset to start at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.reverse = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + if (begin === end) + return this; // Nothing to reverse + Array.prototype.reverse.call(this.view.subarray(begin, end)); + return this; + }; + /** + * Skips the next `length` bytes. This will just advance + * @param {number} length Number of bytes to skip. May also be negative to move the offset back. + * @returns {!ByteBuffer} this + * @expose + */ + ByteBufferPrototype.skip = function(length) { + if (!this.noAssert) { + if (typeof length !== 'number' || length % 1 !== 0) + throw TypeError("Illegal length: "+length+" (not an integer)"); + length |= 0; + } + var offset = this.offset + length; + if (!this.noAssert) { + if (offset < 0 || offset > this.buffer.byteLength) + throw RangeError("Illegal length: 0 <= "+this.offset+" + "+length+" <= "+this.buffer.byteLength); + } + this.offset = offset; + return this; + }; + + /** + * Slices this ByteBuffer by creating a cloned instance with `offset = begin` and `limit = end`. + * @param {number=} begin Begin offset, defaults to {@link ByteBuffer#offset}. + * @param {number=} end End offset, defaults to {@link ByteBuffer#limit}. + * @returns {!ByteBuffer} Clone of this ByteBuffer with slicing applied, backed by the same {@link ByteBuffer#buffer} + * @expose + */ + ByteBufferPrototype.slice = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var bb = this.clone(); + bb.offset = begin; + bb.limit = end; + return bb; + }; + /** + * Returns a copy of the backing buffer that contains this ByteBuffer's contents. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. + * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory if + * possible. Defaults to `false` + * @returns {!ArrayBuffer} Contents as an ArrayBuffer + * @expose + */ + ByteBufferPrototype.toBuffer = function(forceCopy) { + var offset = this.offset, + limit = this.limit; + if (!this.noAssert) { + if (typeof offset !== 'number' || offset % 1 !== 0) + throw TypeError("Illegal offset: Not an integer"); + offset >>>= 0; + if (typeof limit !== 'number' || limit % 1 !== 0) + throw TypeError("Illegal limit: Not an integer"); + limit >>>= 0; + if (offset < 0 || offset > limit || limit > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+offset+" <= "+limit+" <= "+this.buffer.byteLength); + } + // NOTE: It's not possible to have another ArrayBuffer reference the same memory as the backing buffer. This is + // possible with Uint8Array#subarray only, but we have to return an ArrayBuffer by contract. So: + if (!forceCopy && offset === 0 && limit === this.buffer.byteLength) + return this.buffer; + if (offset === limit) + return EMPTY_BUFFER; + var buffer = new ArrayBuffer(limit - offset); + new Uint8Array(buffer).set(new Uint8Array(this.buffer).subarray(offset, limit), 0); + return buffer; + }; + + /** + * Returns a raw buffer compacted to contain this ByteBuffer's contents. Contents are the bytes between + * {@link ByteBuffer#offset} and {@link ByteBuffer#limit}. This is an alias of {@link ByteBuffer#toBuffer}. + * @function + * @param {boolean=} forceCopy If `true` returns a copy, otherwise returns a view referencing the same memory. + * Defaults to `false` + * @returns {!ArrayBuffer} Contents as an ArrayBuffer + * @expose + */ + ByteBufferPrototype.toArrayBuffer = ByteBufferPrototype.toBuffer; + + /** + * Converts the ByteBuffer's contents to a string. + * @param {string=} encoding Output encoding. Returns an informative string representation if omitted but also allows + * direct conversion to "utf8", "hex", "base64" and "binary" encoding. "debug" returns a hex representation with + * highlighted offsets. + * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset} + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit} + * @returns {string} String representation + * @throws {Error} If `encoding` is invalid + * @expose + */ + ByteBufferPrototype.toString = function(encoding, begin, end) { + if (typeof encoding === 'undefined') + return "ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")"; + if (typeof encoding === 'number') + encoding = "utf8", + begin = encoding, + end = begin; + switch (encoding) { + case "utf8": + return this.toUTF8(begin, end); + case "base64": + return this.toBase64(begin, end); + case "hex": + return this.toHex(begin, end); + case "binary": + return this.toBinary(begin, end); + case "debug": + return this.toDebug(); + case "columns": + return this.toColumns(); + default: + throw Error("Unsupported encoding: "+encoding); + } + }; + + // lxiv-embeddable + + /** + * lxiv-embeddable (c) 2014 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/lxiv for details + */ + var lxiv = function() { + "use strict"; + + /** + * lxiv namespace. + * @type {!Object.} + * @exports lxiv + */ + var lxiv = {}; + + /** + * Character codes for output. + * @type {!Array.} + * @inner + */ + var aout = [ + 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, + 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 102, + 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, + 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 43, 47 + ]; + + /** + * Character codes for input. + * @type {!Array.} + * @inner + */ + var ain = []; + for (var i=0, k=aout.length; i>2)&0x3f]); + t = (b&0x3)<<4; + if ((b = src()) !== null) { + t |= (b>>4)&0xf; + dst(aout[(t|((b>>4)&0xf))&0x3f]); + t = (b&0xf)<<2; + if ((b = src()) !== null) + dst(aout[(t|((b>>6)&0x3))&0x3f]), + dst(aout[b&0x3f]); + else + dst(aout[t&0x3f]), + dst(61); + } else + dst(aout[t&0x3f]), + dst(61), + dst(61); + } + }; + + /** + * Decodes base64 char codes to bytes. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. + * @throws {Error} If a character code is invalid + */ + lxiv.decode = function(src, dst) { + var c, t1, t2; + function fail(c) { + throw Error("Illegal character code: "+c); + } + while ((c = src()) !== null) { + t1 = ain[c]; + if (typeof t1 === 'undefined') fail(c); + if ((c = src()) !== null) { + t2 = ain[c]; + if (typeof t2 === 'undefined') fail(c); + dst((t1<<2)>>>0|(t2&0x30)>>4); + if ((c = src()) !== null) { + t1 = ain[c]; + if (typeof t1 === 'undefined') + if (c === 61) break; else fail(c); + dst(((t2&0xf)<<4)>>>0|(t1&0x3c)>>2); + if ((c = src()) !== null) { + t2 = ain[c]; + if (typeof t2 === 'undefined') + if (c === 61) break; else fail(c); + dst(((t1&0x3)<<6)>>>0|t2); + } + } + } + } + }; + + /** + * Tests if a string is valid base64. + * @param {string} str String to test + * @returns {boolean} `true` if valid, otherwise `false` + */ + lxiv.test = function(str) { + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(str); + }; + + return lxiv; + }(); + + // encodings/base64 + + /** + * Encodes this ByteBuffer's contents to a base64 encoded string. + * @param {number=} begin Offset to begin at, defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at, defaults to {@link ByteBuffer#limit}. + * @returns {string} Base64 encoded string + * @throws {RangeError} If `begin` or `end` is out of bounds + * @expose + */ + ByteBufferPrototype.toBase64 = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin = begin | 0; end = end | 0; + if (begin < 0 || end > this.capacity || begin > end) + throw RangeError("begin, end"); + var sd; lxiv.encode(function() { + return begin < end ? this.view[begin++] : null; + }.bind(this), sd = stringDestination()); + return sd(); + }; + + /** + * Decodes a base64 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromBase64 = function(str, littleEndian) { + if (typeof str !== 'string') + throw TypeError("str"); + var bb = new ByteBuffer(str.length/4*3, littleEndian), + i = 0; + lxiv.decode(stringSource(str), function(b) { + bb.view[i++] = b; + }); + bb.limit = i; + return bb; + }; + + /** + * Encodes a binary string to base64 like `window.btoa` does. + * @param {string} str Binary string + * @returns {string} Base64 encoded string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.btoa + * @expose + */ + ByteBuffer.btoa = function(str) { + return ByteBuffer.fromBinary(str).toBase64(); + }; + + /** + * Decodes a base64 encoded string to binary like `window.atob` does. + * @param {string} b64 Base64 encoded string + * @returns {string} Binary string + * @see https://developer.mozilla.org/en-US/docs/Web/API/Window.atob + * @expose + */ + ByteBuffer.atob = function(b64) { + return ByteBuffer.fromBase64(b64).toBinary(); + }; + + // encodings/binary + + /** + * Encodes this ByteBuffer to a binary encoded string, that is using only characters 0x00-0xFF as bytes. + * @param {number=} begin Offset to begin at. Defaults to {@link ByteBuffer#offset}. + * @param {number=} end Offset to end at. Defaults to {@link ByteBuffer#limit}. + * @returns {string} Binary encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ + ByteBufferPrototype.toBinary = function(begin, end) { + if (typeof begin === 'undefined') + begin = this.offset; + if (typeof end === 'undefined') + end = this.limit; + begin |= 0; end |= 0; + if (begin < 0 || end > this.capacity() || begin > end) + throw RangeError("begin, end"); + if (begin === end) + return ""; + var chars = [], + parts = []; + while (begin < end) { + chars.push(this.view[begin++]); + if (chars.length >= 1024) + parts.push(String.fromCharCode.apply(String, chars)), + chars = []; + } + return parts.join('') + String.fromCharCode.apply(String, chars); + }; + + /** + * Decodes a binary encoded string, that is using only characters 0x00-0xFF as bytes, to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromBinary = function(str, littleEndian) { + if (typeof str !== 'string') + throw TypeError("str"); + var i = 0, + k = str.length, + charCode, + bb = new ByteBuffer(k, littleEndian); + while (i 0xff) + throw RangeError("illegal char code: "+charCode); + bb.view[i++] = charCode; + } + bb.limit = k; + return bb; + }; + + // encodings/debug + + /** + * Encodes this ByteBuffer to a hex encoded string with marked offsets. Offset symbols are: + * * `<` : offset, + * * `'` : markedOffset, + * * `>` : limit, + * * `|` : offset and limit, + * * `[` : offset and markedOffset, + * * `]` : markedOffset and limit, + * * `!` : offset, markedOffset and limit + * @param {boolean=} columns If `true` returns two columns hex + ascii, defaults to `false` + * @returns {string|!Array.} Debug string or array of lines if `asArray = true` + * @expose + * @example `>00'01 02<03` contains four bytes with `limit=0, markedOffset=1, offset=3` + * @example `00[01 02 03>` contains four bytes with `offset=markedOffset=1, limit=4` + * @example `00|01 02 03` contains four bytes with `offset=limit=1, markedOffset=-1` + * @example `|` contains zero bytes with `offset=limit=0, markedOffset=-1` + */ + ByteBufferPrototype.toDebug = function(columns) { + var i = -1, + k = this.buffer.byteLength, + b, + hex = "", + asc = "", + out = ""; + while (i 32 && b < 127 ? String.fromCharCode(b) : '.'; + } + ++i; + if (columns) { + if (i > 0 && i % 16 === 0 && i !== k) { + while (hex.length < 3*16+3) hex += " "; + out += hex+asc+"\n"; + hex = asc = ""; + } + } + if (i === this.offset && i === this.limit) + hex += i === this.markedOffset ? "!" : "|"; + else if (i === this.offset) + hex += i === this.markedOffset ? "[" : "<"; + else if (i === this.limit) + hex += i === this.markedOffset ? "]" : ">"; + else + hex += i === this.markedOffset ? "'" : (columns || (i !== 0 && i !== k) ? " " : ""); + } + if (columns && hex !== " ") { + while (hex.length < 3*16+3) + hex += " "; + out += hex + asc + "\n"; + } + return columns ? out : hex; + }; + + /** + * Decodes a hex encoded string with marked offsets to a ByteBuffer. + * @param {string} str Debug string to decode (not be generated with `columns = true`) + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + * @see ByteBuffer#toDebug + */ + ByteBuffer.fromDebug = function(str, littleEndian, noAssert) { + var k = str.length, + bb = new ByteBuffer(((k+1)/3)|0, littleEndian, noAssert); + var i = 0, j = 0, ch, b, + rs = false, // Require symbol next + ho = false, hm = false, hl = false, // Already has offset (ho), markedOffset (hm), limit (hl)? + fail = false; + while (i': + if (!noAssert) { + if (hl) { + fail = true; + break; + } + hl = true; + } + bb.limit = j; + rs = false; + break; + case "'": + if (!noAssert) { + if (hm) { + fail = true; + break; + } + hm = true; + } + bb.markedOffset = j; + rs = false; + break; + case ' ': + rs = false; + break; + default: + if (!noAssert) { + if (rs) { + fail = true; + break; + } + } + b = parseInt(ch+str.charAt(i++), 16); + if (!noAssert) { + if (isNaN(b) || b < 0 || b > 255) + throw TypeError("Illegal str: Not a debug encoded string"); + } + bb.view[j++] = b; + rs = true; + } + if (fail) + throw TypeError("Illegal str: Invalid symbol at "+i); + } + if (!noAssert) { + if (!ho || !hl) + throw TypeError("Illegal str: Missing offset or limit"); + if (j>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var out = new Array(end - begin), + b; + while (begin < end) { + b = this.view[begin++]; + if (b < 0x10) + out.push("0", b.toString(16)); + else out.push(b.toString(16)); + } + return out.join(''); + }; + + /** + * Decodes a hex encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromHex = function(str, littleEndian, noAssert) { + if (!noAssert) { + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + if (str.length % 2 !== 0) + throw TypeError("Illegal str: Length not a multiple of 2"); + } + var k = str.length, + bb = new ByteBuffer((k / 2) | 0, littleEndian), + b; + for (var i=0, j=0; i 255) + throw TypeError("Illegal str: Contains non-hex characters"); + bb.view[j++] = b; + } + bb.limit = j; + return bb; + }; + + // utfx-embeddable + + /** + * utfx-embeddable (c) 2014 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/utfx for details + */ + var utfx = function() { + "use strict"; + + /** + * utfx namespace. + * @inner + * @type {!Object.} + */ + var utfx = {}; + + /** + * Maximum valid code point. + * @type {number} + * @const + */ + utfx.MAX_CODEPOINT = 0x10FFFF; + + /** + * Encodes UTF8 code points to UTF8 bytes. + * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point + * respectively `null` if there are no more code points left or a single numeric code point. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte + */ + utfx.encodeUTF8 = function(src, dst) { + var cp = null; + if (typeof src === 'number') + cp = src, + src = function() { return null; }; + while (cp !== null || (cp = src()) !== null) { + if (cp < 0x80) + dst(cp&0x7F); + else if (cp < 0x800) + dst(((cp>>6)&0x1F)|0xC0), + dst((cp&0x3F)|0x80); + else if (cp < 0x10000) + dst(((cp>>12)&0x0F)|0xE0), + dst(((cp>>6)&0x3F)|0x80), + dst((cp&0x3F)|0x80); + else + dst(((cp>>18)&0x07)|0xF0), + dst(((cp>>12)&0x3F)|0x80), + dst(((cp>>6)&0x3F)|0x80), + dst((cp&0x3F)|0x80); + cp = null; + } + }; + + /** + * Decodes UTF8 bytes to UTF8 code points. + * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there + * are no more bytes left. + * @param {!function(number)} dst Code points destination as a function successively called with each decoded code point. + * @throws {RangeError} If a starting byte is invalid in UTF8 + * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the + * remaining bytes. + */ + utfx.decodeUTF8 = function(src, dst) { + var a, b, c, d, fail = function(b) { + b = b.slice(0, b.indexOf(null)); + var err = Error(b.toString()); + err.name = "TruncatedError"; + err['bytes'] = b; + throw err; + }; + while ((a = src()) !== null) { + if ((a&0x80) === 0) + dst(a); + else if ((a&0xE0) === 0xC0) + ((b = src()) === null) && fail([a, b]), + dst(((a&0x1F)<<6) | (b&0x3F)); + else if ((a&0xF0) === 0xE0) + ((b=src()) === null || (c=src()) === null) && fail([a, b, c]), + dst(((a&0x0F)<<12) | ((b&0x3F)<<6) | (c&0x3F)); + else if ((a&0xF8) === 0xF0) + ((b=src()) === null || (c=src()) === null || (d=src()) === null) && fail([a, b, c ,d]), + dst(((a&0x07)<<18) | ((b&0x3F)<<12) | ((c&0x3F)<<6) | (d&0x3F)); + else throw RangeError("Illegal starting byte: "+a); + } + }; + + /** + * Converts UTF16 characters to UTF8 code points. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @param {!function(number)} dst Code points destination as a function successively called with each converted code + * point. + */ + utfx.UTF16toUTF8 = function(src, dst) { + var c1, c2 = null; + while (true) { + if ((c1 = c2 !== null ? c2 : src()) === null) + break; + if (c1 >= 0xD800 && c1 <= 0xDFFF) { + if ((c2 = src()) !== null) { + if (c2 >= 0xDC00 && c2 <= 0xDFFF) { + dst((c1-0xD800)*0x400+c2-0xDC00+0x10000); + c2 = null; continue; + } + } + } + dst(c1); + } + if (c2 !== null) dst(c2); + }; + + /** + * Converts UTF8 code points to UTF16 characters. + * @param {(!function():number|null) | number} src Code points source, either as a function returning the next code point + * respectively `null` if there are no more code points left or a single numeric code point. + * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. + * @throws {RangeError} If a code point is out of range + */ + utfx.UTF8toUTF16 = function(src, dst) { + var cp = null; + if (typeof src === 'number') + cp = src, src = function() { return null; }; + while (cp !== null || (cp = src()) !== null) { + if (cp <= 0xFFFF) + dst(cp); + else + cp -= 0x10000, + dst((cp>>10)+0xD800), + dst((cp%0x400)+0xDC00); + cp = null; + } + }; + + /** + * Converts and encodes UTF16 characters to UTF8 bytes. + * @param {!function():number|null} src Characters source as a function returning the next char code respectively `null` + * if there are no more characters left. + * @param {!function(number)} dst Bytes destination as a function successively called with the next byte. + */ + utfx.encodeUTF16toUTF8 = function(src, dst) { + utfx.UTF16toUTF8(src, function(cp) { + utfx.encodeUTF8(cp, dst); + }); + }; + + /** + * Decodes and converts UTF8 bytes to UTF16 characters. + * @param {!function():number|null} src Bytes source as a function returning the next byte respectively `null` if there + * are no more bytes left. + * @param {!function(number)} dst Characters destination as a function successively called with each converted char code. + * @throws {RangeError} If a starting byte is invalid in UTF8 + * @throws {Error} If the last sequence is truncated. Has an array property `bytes` holding the remaining bytes. + */ + utfx.decodeUTF8toUTF16 = function(src, dst) { + utfx.decodeUTF8(src, function(cp) { + utfx.UTF8toUTF16(cp, dst); + }); + }; + + /** + * Calculates the byte length of an UTF8 code point. + * @param {number} cp UTF8 code point + * @returns {number} Byte length + */ + utfx.calculateCodePoint = function(cp) { + return (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + }; + + /** + * Calculates the number of UTF8 bytes required to store UTF8 code points. + * @param {(!function():number|null)} src Code points source as a function returning the next code point respectively + * `null` if there are no more code points left. + * @returns {number} The number of UTF8 bytes required + */ + utfx.calculateUTF8 = function(src) { + var cp, l=0; + while ((cp = src()) !== null) + l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + return l; + }; + + /** + * Calculates the number of UTF8 code points respectively UTF8 bytes required to store UTF16 char codes. + * @param {(!function():number|null)} src Characters source as a function returning the next char code respectively + * `null` if there are no more characters left. + * @returns {!Array.} The number of UTF8 code points at index 0 and the number of UTF8 bytes required at index 1. + */ + utfx.calculateUTF16asUTF8 = function(src) { + var n=0, l=0; + utfx.UTF16toUTF8(src, function(cp) { + ++n; l += (cp < 0x80) ? 1 : (cp < 0x800) ? 2 : (cp < 0x10000) ? 3 : 4; + }); + return [n,l]; + }; + + return utfx; + }(); + + // encodings/utf8 + + /** + * Encodes this ByteBuffer's contents between {@link ByteBuffer#offset} and {@link ByteBuffer#limit} to an UTF8 encoded + * string. + * @returns {string} Hex encoded string + * @throws {RangeError} If `offset > limit` + * @expose + */ + ByteBufferPrototype.toUTF8 = function(begin, end) { + if (typeof begin === 'undefined') begin = this.offset; + if (typeof end === 'undefined') end = this.limit; + if (!this.noAssert) { + if (typeof begin !== 'number' || begin % 1 !== 0) + throw TypeError("Illegal begin: Not an integer"); + begin >>>= 0; + if (typeof end !== 'number' || end % 1 !== 0) + throw TypeError("Illegal end: Not an integer"); + end >>>= 0; + if (begin < 0 || begin > end || end > this.buffer.byteLength) + throw RangeError("Illegal range: 0 <= "+begin+" <= "+end+" <= "+this.buffer.byteLength); + } + var sd; try { + utfx.decodeUTF8toUTF16(function() { + return begin < end ? this.view[begin++] : null; + }.bind(this), sd = stringDestination()); + } catch (e) { + if (begin !== end) + throw RangeError("Illegal range: Truncated data, "+begin+" != "+end); + } + return sd(); + }; + + /** + * Decodes an UTF8 encoded string to a ByteBuffer. + * @param {string} str String to decode + * @param {boolean=} littleEndian Whether to use little or big endian byte order. Defaults to + * {@link ByteBuffer.DEFAULT_ENDIAN}. + * @param {boolean=} noAssert Whether to skip assertions of offsets and values. Defaults to + * {@link ByteBuffer.DEFAULT_NOASSERT}. + * @returns {!ByteBuffer} ByteBuffer + * @expose + */ + ByteBuffer.fromUTF8 = function(str, littleEndian, noAssert) { + if (!noAssert) + if (typeof str !== 'string') + throw TypeError("Illegal str: Not a string"); + var bb = new ByteBuffer(utfx.calculateUTF16asUTF8(stringSource(str), true)[1], littleEndian, noAssert), + i = 0; + utfx.encodeUTF16toUTF8(stringSource(str), function(b) { + bb.view[i++] = b; + }); + bb.limit = i; + return bb; + }; + + return ByteBuffer; +}); + +},{"long":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/long/dist/long.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/cipher-base/index.js":[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer +var Transform = require('stream').Transform +var StringDecoder = require('string_decoder').StringDecoder +var inherits = require('inherits') + +function CipherBase (hashMode) { + Transform.call(this) + this.hashMode = typeof hashMode === 'string' + if (this.hashMode) { + this[hashMode] = this._finalOrDigest + } else { + this.final = this._finalOrDigest + } + if (this._final) { + this.__final = this._final + this._final = null + } + this._decoder = null + this._encoding = null +} +inherits(CipherBase, Transform) + +CipherBase.prototype.update = function (data, inputEnc, outputEnc) { + if (typeof data === 'string') { + data = Buffer.from(data, inputEnc) + } + + var outData = this._update(data) + if (this.hashMode) return this + + if (outputEnc) { + outData = this._toString(outData, outputEnc) + } + + return outData +} + +CipherBase.prototype.setAutoPadding = function () {} +CipherBase.prototype.getAuthTag = function () { + throw new Error('trying to get auth tag in unsupported state') +} + +CipherBase.prototype.setAuthTag = function () { + throw new Error('trying to set auth tag in unsupported state') +} + +CipherBase.prototype.setAAD = function () { + throw new Error('trying to set aad in unsupported state') +} + +CipherBase.prototype._transform = function (data, _, next) { + var err + try { + if (this.hashMode) { + this._update(data) + } else { + this.push(this._update(data)) + } + } catch (e) { + err = e + } finally { + next(err) + } +} +CipherBase.prototype._flush = function (done) { + var err + try { + this.push(this.__final()) + } catch (e) { + err = e + } + + done(err) +} +CipherBase.prototype._finalOrDigest = function (outputEnc) { + var outData = this.__final() || Buffer.alloc(0) + if (outputEnc) { + outData = this._toString(outData, outputEnc, true) + } + return outData +} + +CipherBase.prototype._toString = function (value, enc, fin) { + if (!this._decoder) { + this._decoder = new StringDecoder(enc) + this._encoding = enc + } + + if (this._encoding !== enc) throw new Error('can\'t switch encodings') + + var out = this._decoder.write(value) + if (fin) { + out += this._decoder.end() + } + + return out +} + +module.exports = CipherBase + +},{"inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js","stream":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/stream-browserify/index.js","string_decoder":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/string_decoder/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/core-util-is/lib/util.js":[function(require,module,exports){ +(function (Buffer){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. + +function isArray(arg) { + if (Array.isArray) { + return Array.isArray(arg); + } + return objectToString(arg) === '[object Array]'; +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = Buffer.isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + +}).call(this,{"isBuffer":require("../../is-buffer/index.js")}) + +},{"../../is-buffer/index.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/is-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/create-hash/browser.js":[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var MD5 = require('md5.js') +var RIPEMD160 = require('ripemd160') +var sha = require('sha.js') +var Base = require('cipher-base') + +function Hash (hash) { + Base.call(this, 'digest') + + this._hash = hash +} + +inherits(Hash, Base) + +Hash.prototype._update = function (data) { + this._hash.update(data) +} + +Hash.prototype._final = function () { + return this._hash.digest() +} + +module.exports = function createHash (alg) { + alg = alg.toLowerCase() + if (alg === 'md5') return new MD5() + if (alg === 'rmd160' || alg === 'ripemd160') return new RIPEMD160() + + return new Hash(sha(alg)) +} + +},{"cipher-base":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/cipher-base/index.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","md5.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/md5.js/index.js","ripemd160":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ripemd160/index.js","sha.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/create-hash/md5.js":[function(require,module,exports){ +var MD5 = require('md5.js') + +module.exports = function (buffer) { + return new MD5().update(buffer).digest() +} + +},{"md5.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/md5.js/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/create-hmac/browser.js":[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var Legacy = require('./legacy') +var Base = require('cipher-base') +var Buffer = require('safe-buffer').Buffer +var md5 = require('create-hash/md5') +var RIPEMD160 = require('ripemd160') + +var sha = require('sha.js') + +var ZEROS = Buffer.alloc(128) + +function Hmac (alg, key) { + Base.call(this, 'digest') + if (typeof key === 'string') { + key = Buffer.from(key) + } + + var blocksize = (alg === 'sha512' || alg === 'sha384') ? 128 : 64 + + this._alg = alg + this._key = key + if (key.length > blocksize) { + var hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) + key = hash.update(key).digest() + } else if (key.length < blocksize) { + key = Buffer.concat([key, ZEROS], blocksize) + } + + var ipad = this._ipad = Buffer.allocUnsafe(blocksize) + var opad = this._opad = Buffer.allocUnsafe(blocksize) + + for (var i = 0; i < blocksize; i++) { + ipad[i] = key[i] ^ 0x36 + opad[i] = key[i] ^ 0x5C + } + this._hash = alg === 'rmd160' ? new RIPEMD160() : sha(alg) + this._hash.update(ipad) +} + +inherits(Hmac, Base) + +Hmac.prototype._update = function (data) { + this._hash.update(data) +} + +Hmac.prototype._final = function () { + var h = this._hash.digest() + var hash = this._alg === 'rmd160' ? new RIPEMD160() : sha(this._alg) + return hash.update(this._opad).update(h).digest() +} + +module.exports = function createHmac (alg, key) { + alg = alg.toLowerCase() + if (alg === 'rmd160' || alg === 'ripemd160') { + return new Hmac('rmd160', key) + } + if (alg === 'md5') { + return new Legacy(md5, key) + } + return new Hmac(alg, key) +} + +},{"./legacy":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/create-hmac/legacy.js","cipher-base":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/cipher-base/index.js","create-hash/md5":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/create-hash/md5.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","ripemd160":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ripemd160/index.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js","sha.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/create-hmac/legacy.js":[function(require,module,exports){ +'use strict' +var inherits = require('inherits') +var Buffer = require('safe-buffer').Buffer + +var Base = require('cipher-base') + +var ZEROS = Buffer.alloc(128) +var blocksize = 64 + +function Hmac (alg, key) { + Base.call(this, 'digest') + if (typeof key === 'string') { + key = Buffer.from(key) + } + + this._alg = alg + this._key = key + + if (key.length > blocksize) { + key = alg(key) + } else if (key.length < blocksize) { + key = Buffer.concat([key, ZEROS], blocksize) + } + + var ipad = this._ipad = Buffer.allocUnsafe(blocksize) + var opad = this._opad = Buffer.allocUnsafe(blocksize) + + for (var i = 0; i < blocksize; i++) { + ipad[i] = key[i] ^ 0x36 + opad[i] = key[i] ^ 0x5C + } + + this._hash = [ipad] +} + +inherits(Hmac, Base) + +Hmac.prototype._update = function (data) { + this._hash.push(data) +} + +Hmac.prototype._final = function () { + var h = this._alg(Buffer.concat(this._hash)) + return this._alg(Buffer.concat([this._opad, h])) +} +module.exports = Hmac + +},{"cipher-base":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/cipher-base/index.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/aes.js":[function(require,module,exports){ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./enc-base64"), require("./md5"), require("./evpkdf"), require("./cipher-core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./enc-base64", "./md5", "./evpkdf", "./cipher-core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var BlockCipher = C_lib.BlockCipher; + var C_algo = C.algo; + + // Lookup tables + var SBOX = []; + var INV_SBOX = []; + var SUB_MIX_0 = []; + var SUB_MIX_1 = []; + var SUB_MIX_2 = []; + var SUB_MIX_3 = []; + var INV_SUB_MIX_0 = []; + var INV_SUB_MIX_1 = []; + var INV_SUB_MIX_2 = []; + var INV_SUB_MIX_3 = []; + + // Compute lookup tables + (function () { + // Compute double table + var d = []; + for (var i = 0; i < 256; i++) { + if (i < 128) { + d[i] = i << 1; + } else { + d[i] = (i << 1) ^ 0x11b; + } + } + + // Walk GF(2^8) + var x = 0; + var xi = 0; + for (var i = 0; i < 256; i++) { + // Compute sbox + var sx = xi ^ (xi << 1) ^ (xi << 2) ^ (xi << 3) ^ (xi << 4); + sx = (sx >>> 8) ^ (sx & 0xff) ^ 0x63; + SBOX[x] = sx; + INV_SBOX[sx] = x; + + // Compute multiplication + var x2 = d[x]; + var x4 = d[x2]; + var x8 = d[x4]; + + // Compute sub bytes, mix columns tables + var t = (d[sx] * 0x101) ^ (sx * 0x1010100); + SUB_MIX_0[x] = (t << 24) | (t >>> 8); + SUB_MIX_1[x] = (t << 16) | (t >>> 16); + SUB_MIX_2[x] = (t << 8) | (t >>> 24); + SUB_MIX_3[x] = t; + + // Compute inv sub bytes, inv mix columns tables + var t = (x8 * 0x1010101) ^ (x4 * 0x10001) ^ (x2 * 0x101) ^ (x * 0x1010100); + INV_SUB_MIX_0[sx] = (t << 24) | (t >>> 8); + INV_SUB_MIX_1[sx] = (t << 16) | (t >>> 16); + INV_SUB_MIX_2[sx] = (t << 8) | (t >>> 24); + INV_SUB_MIX_3[sx] = t; + + // Compute next counter + if (!x) { + x = xi = 1; + } else { + x = x2 ^ d[d[d[x8 ^ x2]]]; + xi ^= d[d[xi]]; + } + } + }()); + + // Precomputed Rcon lookup + var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36]; + + /** + * AES block cipher algorithm. + */ + var AES = C_algo.AES = BlockCipher.extend({ + _doReset: function () { + // Skip reset of nRounds has been set before and key did not change + if (this._nRounds && this._keyPriorReset === this._key) { + return; + } + + // Shortcuts + var key = this._keyPriorReset = this._key; + var keyWords = key.words; + var keySize = key.sigBytes / 4; + + // Compute number of rounds + var nRounds = this._nRounds = keySize + 6; + + // Compute number of key schedule rows + var ksRows = (nRounds + 1) * 4; + + // Compute key schedule + var keySchedule = this._keySchedule = []; + for (var ksRow = 0; ksRow < ksRows; ksRow++) { + if (ksRow < keySize) { + keySchedule[ksRow] = keyWords[ksRow]; + } else { + var t = keySchedule[ksRow - 1]; + + if (!(ksRow % keySize)) { + // Rot word + t = (t << 8) | (t >>> 24); + + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + + // Mix Rcon + t ^= RCON[(ksRow / keySize) | 0] << 24; + } else if (keySize > 6 && ksRow % keySize == 4) { + // Sub word + t = (SBOX[t >>> 24] << 24) | (SBOX[(t >>> 16) & 0xff] << 16) | (SBOX[(t >>> 8) & 0xff] << 8) | SBOX[t & 0xff]; + } + + keySchedule[ksRow] = keySchedule[ksRow - keySize] ^ t; + } + } + + // Compute inv key schedule + var invKeySchedule = this._invKeySchedule = []; + for (var invKsRow = 0; invKsRow < ksRows; invKsRow++) { + var ksRow = ksRows - invKsRow; + + if (invKsRow % 4) { + var t = keySchedule[ksRow]; + } else { + var t = keySchedule[ksRow - 4]; + } + + if (invKsRow < 4 || ksRow <= 4) { + invKeySchedule[invKsRow] = t; + } else { + invKeySchedule[invKsRow] = INV_SUB_MIX_0[SBOX[t >>> 24]] ^ INV_SUB_MIX_1[SBOX[(t >>> 16) & 0xff]] ^ + INV_SUB_MIX_2[SBOX[(t >>> 8) & 0xff]] ^ INV_SUB_MIX_3[SBOX[t & 0xff]]; + } + } + }, + + encryptBlock: function (M, offset) { + this._doCryptBlock(M, offset, this._keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX); + }, + + decryptBlock: function (M, offset) { + // Swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + + this._doCryptBlock(M, offset, this._invKeySchedule, INV_SUB_MIX_0, INV_SUB_MIX_1, INV_SUB_MIX_2, INV_SUB_MIX_3, INV_SBOX); + + // Inv swap 2nd and 4th rows + var t = M[offset + 1]; + M[offset + 1] = M[offset + 3]; + M[offset + 3] = t; + }, + + _doCryptBlock: function (M, offset, keySchedule, SUB_MIX_0, SUB_MIX_1, SUB_MIX_2, SUB_MIX_3, SBOX) { + // Shortcut + var nRounds = this._nRounds; + + // Get input, add round key + var s0 = M[offset] ^ keySchedule[0]; + var s1 = M[offset + 1] ^ keySchedule[1]; + var s2 = M[offset + 2] ^ keySchedule[2]; + var s3 = M[offset + 3] ^ keySchedule[3]; + + // Key schedule row counter + var ksRow = 4; + + // Rounds + for (var round = 1; round < nRounds; round++) { + // Shift rows, sub bytes, mix columns, add round key + var t0 = SUB_MIX_0[s0 >>> 24] ^ SUB_MIX_1[(s1 >>> 16) & 0xff] ^ SUB_MIX_2[(s2 >>> 8) & 0xff] ^ SUB_MIX_3[s3 & 0xff] ^ keySchedule[ksRow++]; + var t1 = SUB_MIX_0[s1 >>> 24] ^ SUB_MIX_1[(s2 >>> 16) & 0xff] ^ SUB_MIX_2[(s3 >>> 8) & 0xff] ^ SUB_MIX_3[s0 & 0xff] ^ keySchedule[ksRow++]; + var t2 = SUB_MIX_0[s2 >>> 24] ^ SUB_MIX_1[(s3 >>> 16) & 0xff] ^ SUB_MIX_2[(s0 >>> 8) & 0xff] ^ SUB_MIX_3[s1 & 0xff] ^ keySchedule[ksRow++]; + var t3 = SUB_MIX_0[s3 >>> 24] ^ SUB_MIX_1[(s0 >>> 16) & 0xff] ^ SUB_MIX_2[(s1 >>> 8) & 0xff] ^ SUB_MIX_3[s2 & 0xff] ^ keySchedule[ksRow++]; + + // Update state + s0 = t0; + s1 = t1; + s2 = t2; + s3 = t3; + } + + // Shift rows, sub bytes, add round key + var t0 = ((SBOX[s0 >>> 24] << 24) | (SBOX[(s1 >>> 16) & 0xff] << 16) | (SBOX[(s2 >>> 8) & 0xff] << 8) | SBOX[s3 & 0xff]) ^ keySchedule[ksRow++]; + var t1 = ((SBOX[s1 >>> 24] << 24) | (SBOX[(s2 >>> 16) & 0xff] << 16) | (SBOX[(s3 >>> 8) & 0xff] << 8) | SBOX[s0 & 0xff]) ^ keySchedule[ksRow++]; + var t2 = ((SBOX[s2 >>> 24] << 24) | (SBOX[(s3 >>> 16) & 0xff] << 16) | (SBOX[(s0 >>> 8) & 0xff] << 8) | SBOX[s1 & 0xff]) ^ keySchedule[ksRow++]; + var t3 = ((SBOX[s3 >>> 24] << 24) | (SBOX[(s0 >>> 16) & 0xff] << 16) | (SBOX[(s1 >>> 8) & 0xff] << 8) | SBOX[s2 & 0xff]) ^ keySchedule[ksRow++]; + + // Set output + M[offset] = t0; + M[offset + 1] = t1; + M[offset + 2] = t2; + M[offset + 3] = t3; + }, + + keySize: 256/32 + }); + + /** + * Shortcut functions to the cipher's object interface. + * + * @example + * + * var ciphertext = CryptoJS.AES.encrypt(message, key, cfg); + * var plaintext = CryptoJS.AES.decrypt(ciphertext, key, cfg); + */ + C.AES = BlockCipher._createHelper(AES); + }()); + + + return CryptoJS.AES; + +})); +},{"./cipher-core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/cipher-core.js","./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js","./enc-base64":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/enc-base64.js","./evpkdf":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/evpkdf.js","./md5":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/md5.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/cipher-core.js":[function(require,module,exports){ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + /** + * Cipher core components. + */ + CryptoJS.lib.Cipher || (function (undefined) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var Base64 = C_enc.Base64; + var C_algo = C.algo; + var EvpKDF = C_algo.EvpKDF; + + /** + * Abstract base cipher template. + * + * @property {number} keySize This cipher's key size. Default: 4 (128 bits) + * @property {number} ivSize This cipher's IV size. Default: 4 (128 bits) + * @property {number} _ENC_XFORM_MODE A constant representing encryption mode. + * @property {number} _DEC_XFORM_MODE A constant representing decryption mode. + */ + var Cipher = C_lib.Cipher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + * + * @property {WordArray} iv The IV to use for this operation. + */ + cfg: Base.extend(), + + /** + * Creates this cipher in encryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createEncryptor(keyWordArray, { iv: ivWordArray }); + */ + createEncryptor: function (key, cfg) { + return this.create(this._ENC_XFORM_MODE, key, cfg); + }, + + /** + * Creates this cipher in decryption mode. + * + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {Cipher} A cipher instance. + * + * @static + * + * @example + * + * var cipher = CryptoJS.algo.AES.createDecryptor(keyWordArray, { iv: ivWordArray }); + */ + createDecryptor: function (key, cfg) { + return this.create(this._DEC_XFORM_MODE, key, cfg); + }, + + /** + * Initializes a newly created cipher. + * + * @param {number} xformMode Either the encryption or decryption transormation mode constant. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @example + * + * var cipher = CryptoJS.algo.AES.create(CryptoJS.algo.AES._ENC_XFORM_MODE, keyWordArray, { iv: ivWordArray }); + */ + init: function (xformMode, key, cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Store transform mode and key + this._xformMode = xformMode; + this._key = key; + + // Set initial values + this.reset(); + }, + + /** + * Resets this cipher to its initial state. + * + * @example + * + * cipher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-cipher logic + this._doReset(); + }, + + /** + * Adds data to be encrypted or decrypted. + * + * @param {WordArray|string} dataUpdate The data to encrypt or decrypt. + * + * @return {WordArray} The data after processing. + * + * @example + * + * var encrypted = cipher.process('data'); + * var encrypted = cipher.process(wordArray); + */ + process: function (dataUpdate) { + // Append + this._append(dataUpdate); + + // Process available blocks + return this._process(); + }, + + /** + * Finalizes the encryption or decryption process. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} dataUpdate The final data to encrypt or decrypt. + * + * @return {WordArray} The data after final processing. + * + * @example + * + * var encrypted = cipher.finalize(); + * var encrypted = cipher.finalize('data'); + * var encrypted = cipher.finalize(wordArray); + */ + finalize: function (dataUpdate) { + // Final data update + if (dataUpdate) { + this._append(dataUpdate); + } + + // Perform concrete-cipher logic + var finalProcessedData = this._doFinalize(); + + return finalProcessedData; + }, + + keySize: 128/32, + + ivSize: 128/32, + + _ENC_XFORM_MODE: 1, + + _DEC_XFORM_MODE: 2, + + /** + * Creates shortcut functions to a cipher's object interface. + * + * @param {Cipher} cipher The cipher to create a helper for. + * + * @return {Object} An object with encrypt and decrypt shortcut functions. + * + * @static + * + * @example + * + * var AES = CryptoJS.lib.Cipher._createHelper(CryptoJS.algo.AES); + */ + _createHelper: (function () { + function selectCipherStrategy(key) { + if (typeof key == 'string') { + return PasswordBasedCipher; + } else { + return SerializableCipher; + } + } + + return function (cipher) { + return { + encrypt: function (message, key, cfg) { + return selectCipherStrategy(key).encrypt(cipher, message, key, cfg); + }, + + decrypt: function (ciphertext, key, cfg) { + return selectCipherStrategy(key).decrypt(cipher, ciphertext, key, cfg); + } + }; + }; + }()) + }); + + /** + * Abstract base stream cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 1 (32 bits) + */ + var StreamCipher = C_lib.StreamCipher = Cipher.extend({ + _doFinalize: function () { + // Process partial blocks + var finalProcessedBlocks = this._process(!!'flush'); + + return finalProcessedBlocks; + }, + + blockSize: 1 + }); + + /** + * Mode namespace. + */ + var C_mode = C.mode = {}; + + /** + * Abstract base block cipher mode template. + */ + var BlockCipherMode = C_lib.BlockCipherMode = Base.extend({ + /** + * Creates this mode for encryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createEncryptor(cipher, iv.words); + */ + createEncryptor: function (cipher, iv) { + return this.Encryptor.create(cipher, iv); + }, + + /** + * Creates this mode for decryption. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @static + * + * @example + * + * var mode = CryptoJS.mode.CBC.createDecryptor(cipher, iv.words); + */ + createDecryptor: function (cipher, iv) { + return this.Decryptor.create(cipher, iv); + }, + + /** + * Initializes a newly created mode. + * + * @param {Cipher} cipher A block cipher instance. + * @param {Array} iv The IV words. + * + * @example + * + * var mode = CryptoJS.mode.CBC.Encryptor.create(cipher, iv.words); + */ + init: function (cipher, iv) { + this._cipher = cipher; + this._iv = iv; + } + }); + + /** + * Cipher Block Chaining mode. + */ + var CBC = C_mode.CBC = (function () { + /** + * Abstract base CBC mode. + */ + var CBC = BlockCipherMode.extend(); + + /** + * CBC encryptor. + */ + CBC.Encryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // XOR and encrypt + xorBlock.call(this, words, offset, blockSize); + cipher.encryptBlock(words, offset); + + // Remember this block to use with next block + this._prevBlock = words.slice(offset, offset + blockSize); + } + }); + + /** + * CBC decryptor. + */ + CBC.Decryptor = CBC.extend({ + /** + * Processes the data block at offset. + * + * @param {Array} words The data words to operate on. + * @param {number} offset The offset where the block starts. + * + * @example + * + * mode.processBlock(data.words, offset); + */ + processBlock: function (words, offset) { + // Shortcuts + var cipher = this._cipher; + var blockSize = cipher.blockSize; + + // Remember this block to use with next block + var thisBlock = words.slice(offset, offset + blockSize); + + // Decrypt and XOR + cipher.decryptBlock(words, offset); + xorBlock.call(this, words, offset, blockSize); + + // This block becomes the previous block + this._prevBlock = thisBlock; + } + }); + + function xorBlock(words, offset, blockSize) { + // Shortcut + var iv = this._iv; + + // Choose mixing block + if (iv) { + var block = iv; + + // Remove IV for subsequent blocks + this._iv = undefined; + } else { + var block = this._prevBlock; + } + + // XOR blocks + for (var i = 0; i < blockSize; i++) { + words[offset + i] ^= block[i]; + } + } + + return CBC; + }()); + + /** + * Padding namespace. + */ + var C_pad = C.pad = {}; + + /** + * PKCS #5/7 padding strategy. + */ + var Pkcs7 = C_pad.Pkcs7 = { + /** + * Pads data using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to pad. + * @param {number} blockSize The multiple that the data should be padded to. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.pad(wordArray, 4); + */ + pad: function (data, blockSize) { + // Shortcut + var blockSizeBytes = blockSize * 4; + + // Count padding bytes + var nPaddingBytes = blockSizeBytes - data.sigBytes % blockSizeBytes; + + // Create padding word + var paddingWord = (nPaddingBytes << 24) | (nPaddingBytes << 16) | (nPaddingBytes << 8) | nPaddingBytes; + + // Create padding + var paddingWords = []; + for (var i = 0; i < nPaddingBytes; i += 4) { + paddingWords.push(paddingWord); + } + var padding = WordArray.create(paddingWords, nPaddingBytes); + + // Add padding + data.concat(padding); + }, + + /** + * Unpads data that had been padded using the algorithm defined in PKCS #5/7. + * + * @param {WordArray} data The data to unpad. + * + * @static + * + * @example + * + * CryptoJS.pad.Pkcs7.unpad(wordArray); + */ + unpad: function (data) { + // Get number of padding bytes from last byte + var nPaddingBytes = data.words[(data.sigBytes - 1) >>> 2] & 0xff; + + // Remove padding + data.sigBytes -= nPaddingBytes; + } + }; + + /** + * Abstract base block cipher template. + * + * @property {number} blockSize The number of 32-bit words this cipher operates on. Default: 4 (128 bits) + */ + var BlockCipher = C_lib.BlockCipher = Cipher.extend({ + /** + * Configuration options. + * + * @property {Mode} mode The block mode to use. Default: CBC + * @property {Padding} padding The padding strategy to use. Default: Pkcs7 + */ + cfg: Cipher.cfg.extend({ + mode: CBC, + padding: Pkcs7 + }), + + reset: function () { + // Reset cipher + Cipher.reset.call(this); + + // Shortcuts + var cfg = this.cfg; + var iv = cfg.iv; + var mode = cfg.mode; + + // Reset block mode + if (this._xformMode == this._ENC_XFORM_MODE) { + var modeCreator = mode.createEncryptor; + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + var modeCreator = mode.createDecryptor; + + // Keep at least one block in the buffer for unpadding + this._minBufferSize = 1; + } + this._mode = modeCreator.call(mode, this, iv && iv.words); + }, + + _doProcessBlock: function (words, offset) { + this._mode.processBlock(words, offset); + }, + + _doFinalize: function () { + // Shortcut + var padding = this.cfg.padding; + + // Finalize + if (this._xformMode == this._ENC_XFORM_MODE) { + // Pad data + padding.pad(this._data, this.blockSize); + + // Process final blocks + var finalProcessedBlocks = this._process(!!'flush'); + } else /* if (this._xformMode == this._DEC_XFORM_MODE) */ { + // Process final blocks + var finalProcessedBlocks = this._process(!!'flush'); + + // Unpad data + padding.unpad(finalProcessedBlocks); + } + + return finalProcessedBlocks; + }, + + blockSize: 128/32 + }); + + /** + * A collection of cipher parameters. + * + * @property {WordArray} ciphertext The raw ciphertext. + * @property {WordArray} key The key to this ciphertext. + * @property {WordArray} iv The IV used in the ciphering operation. + * @property {WordArray} salt The salt used with a key derivation function. + * @property {Cipher} algorithm The cipher algorithm. + * @property {Mode} mode The block mode used in the ciphering operation. + * @property {Padding} padding The padding scheme used in the ciphering operation. + * @property {number} blockSize The block size of the cipher. + * @property {Format} formatter The default formatting strategy to convert this cipher params object to a string. + */ + var CipherParams = C_lib.CipherParams = Base.extend({ + /** + * Initializes a newly created cipher params object. + * + * @param {Object} cipherParams An object with any of the possible cipher parameters. + * + * @example + * + * var cipherParams = CryptoJS.lib.CipherParams.create({ + * ciphertext: ciphertextWordArray, + * key: keyWordArray, + * iv: ivWordArray, + * salt: saltWordArray, + * algorithm: CryptoJS.algo.AES, + * mode: CryptoJS.mode.CBC, + * padding: CryptoJS.pad.PKCS7, + * blockSize: 4, + * formatter: CryptoJS.format.OpenSSL + * }); + */ + init: function (cipherParams) { + this.mixIn(cipherParams); + }, + + /** + * Converts this cipher params object to a string. + * + * @param {Format} formatter (Optional) The formatting strategy to use. + * + * @return {string} The stringified cipher params. + * + * @throws Error If neither the formatter nor the default formatter is set. + * + * @example + * + * var string = cipherParams + ''; + * var string = cipherParams.toString(); + * var string = cipherParams.toString(CryptoJS.format.OpenSSL); + */ + toString: function (formatter) { + return (formatter || this.formatter).stringify(this); + } + }); + + /** + * Format namespace. + */ + var C_format = C.format = {}; + + /** + * OpenSSL formatting strategy. + */ + var OpenSSLFormatter = C_format.OpenSSL = { + /** + * Converts a cipher params object to an OpenSSL-compatible string. + * + * @param {CipherParams} cipherParams The cipher params object. + * + * @return {string} The OpenSSL-compatible string. + * + * @static + * + * @example + * + * var openSSLString = CryptoJS.format.OpenSSL.stringify(cipherParams); + */ + stringify: function (cipherParams) { + // Shortcuts + var ciphertext = cipherParams.ciphertext; + var salt = cipherParams.salt; + + // Format + if (salt) { + var wordArray = WordArray.create([0x53616c74, 0x65645f5f]).concat(salt).concat(ciphertext); + } else { + var wordArray = ciphertext; + } + + return wordArray.toString(Base64); + }, + + /** + * Converts an OpenSSL-compatible string to a cipher params object. + * + * @param {string} openSSLStr The OpenSSL-compatible string. + * + * @return {CipherParams} The cipher params object. + * + * @static + * + * @example + * + * var cipherParams = CryptoJS.format.OpenSSL.parse(openSSLString); + */ + parse: function (openSSLStr) { + // Parse base64 + var ciphertext = Base64.parse(openSSLStr); + + // Shortcut + var ciphertextWords = ciphertext.words; + + // Test for salt + if (ciphertextWords[0] == 0x53616c74 && ciphertextWords[1] == 0x65645f5f) { + // Extract salt + var salt = WordArray.create(ciphertextWords.slice(2, 4)); + + // Remove salt from ciphertext + ciphertextWords.splice(0, 4); + ciphertext.sigBytes -= 16; + } + + return CipherParams.create({ ciphertext: ciphertext, salt: salt }); + } + }; + + /** + * A cipher wrapper that returns ciphertext as a serializable cipher params object. + */ + var SerializableCipher = C_lib.SerializableCipher = Base.extend({ + /** + * Configuration options. + * + * @property {Formatter} format The formatting strategy to convert cipher param objects to and from a string. Default: OpenSSL + */ + cfg: Base.extend({ + format: OpenSSLFormatter + }), + + /** + * Encrypts a message. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv }); + * var ciphertextParams = CryptoJS.lib.SerializableCipher.encrypt(CryptoJS.algo.AES, message, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Encrypt + var encryptor = cipher.createEncryptor(key, cfg); + var ciphertext = encryptor.finalize(message); + + // Shortcut + var cipherCfg = encryptor.cfg; + + // Create and return serializable cipher params + return CipherParams.create({ + ciphertext: ciphertext, + key: key, + iv: cipherCfg.iv, + algorithm: cipher, + mode: cipherCfg.mode, + padding: cipherCfg.padding, + blockSize: cipher.blockSize, + formatter: cfg.format + }); + }, + + /** + * Decrypts serialized ciphertext. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {WordArray} key The key. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.SerializableCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, key, { iv: iv, format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, key, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Decrypt + var plaintext = cipher.createDecryptor(key, cfg).finalize(ciphertext.ciphertext); + + return plaintext; + }, + + /** + * Converts serialized ciphertext to CipherParams, + * else assumed CipherParams already and returns ciphertext unchanged. + * + * @param {CipherParams|string} ciphertext The ciphertext. + * @param {Formatter} format The formatting strategy to use to parse serialized ciphertext. + * + * @return {CipherParams} The unserialized ciphertext. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.SerializableCipher._parse(ciphertextStringOrParams, format); + */ + _parse: function (ciphertext, format) { + if (typeof ciphertext == 'string') { + return format.parse(ciphertext, this); + } else { + return ciphertext; + } + } + }); + + /** + * Key derivation function namespace. + */ + var C_kdf = C.kdf = {}; + + /** + * OpenSSL key derivation function. + */ + var OpenSSLKdf = C_kdf.OpenSSL = { + /** + * Derives a key and IV from a password. + * + * @param {string} password The password to derive from. + * @param {number} keySize The size in words of the key to generate. + * @param {number} ivSize The size in words of the IV to generate. + * @param {WordArray|string} salt (Optional) A 64-bit salt to use. If omitted, a salt will be generated randomly. + * + * @return {CipherParams} A cipher params object with the key, IV, and salt. + * + * @static + * + * @example + * + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32); + * var derivedParams = CryptoJS.kdf.OpenSSL.execute('Password', 256/32, 128/32, 'saltsalt'); + */ + execute: function (password, keySize, ivSize, salt) { + // Generate random salt + if (!salt) { + salt = WordArray.random(64/8); + } + + // Derive key and IV + var key = EvpKDF.create({ keySize: keySize + ivSize }).compute(password, salt); + + // Separate key and IV + var iv = WordArray.create(key.words.slice(keySize), ivSize * 4); + key.sigBytes = keySize * 4; + + // Return params + return CipherParams.create({ key: key, iv: iv, salt: salt }); + } + }; + + /** + * A serializable cipher wrapper that derives the key from a password, + * and returns ciphertext as a serializable cipher params object. + */ + var PasswordBasedCipher = C_lib.PasswordBasedCipher = SerializableCipher.extend({ + /** + * Configuration options. + * + * @property {KDF} kdf The key derivation function to use to generate a key and IV from a password. Default: OpenSSL + */ + cfg: SerializableCipher.cfg.extend({ + kdf: OpenSSLKdf + }), + + /** + * Encrypts a message using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {WordArray|string} message The message to encrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {CipherParams} A cipher params object. + * + * @static + * + * @example + * + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password'); + * var ciphertextParams = CryptoJS.lib.PasswordBasedCipher.encrypt(CryptoJS.algo.AES, message, 'password', { format: CryptoJS.format.OpenSSL }); + */ + encrypt: function (cipher, message, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Encrypt + var ciphertext = SerializableCipher.encrypt.call(this, cipher, message, derivedParams.key, cfg); + + // Mix in derived params + ciphertext.mixIn(derivedParams); + + return ciphertext; + }, + + /** + * Decrypts serialized ciphertext using a password. + * + * @param {Cipher} cipher The cipher algorithm to use. + * @param {CipherParams|string} ciphertext The ciphertext to decrypt. + * @param {string} password The password. + * @param {Object} cfg (Optional) The configuration options to use for this operation. + * + * @return {WordArray} The plaintext. + * + * @static + * + * @example + * + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, formattedCiphertext, 'password', { format: CryptoJS.format.OpenSSL }); + * var plaintext = CryptoJS.lib.PasswordBasedCipher.decrypt(CryptoJS.algo.AES, ciphertextParams, 'password', { format: CryptoJS.format.OpenSSL }); + */ + decrypt: function (cipher, ciphertext, password, cfg) { + // Apply config defaults + cfg = this.cfg.extend(cfg); + + // Convert string to CipherParams + ciphertext = this._parse(ciphertext, cfg.format); + + // Derive key and other params + var derivedParams = cfg.kdf.execute(password, cipher.keySize, cipher.ivSize, ciphertext.salt); + + // Add IV to config + cfg.iv = derivedParams.iv; + + // Decrypt + var plaintext = SerializableCipher.decrypt.call(this, cipher, ciphertext, derivedParams.key, cfg); + + return plaintext; + } + }); + }()); + + +})); +},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js":[function(require,module,exports){ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(); + } + else if (typeof define === "function" && define.amd) { + // AMD + define([], factory); + } + else { + // Global (browser) + root.CryptoJS = factory(); + } +}(this, function () { + + /** + * CryptoJS core components. + */ + var CryptoJS = CryptoJS || (function (Math, undefined) { + /* + * Local polyfil of Object.create + */ + var create = Object.create || (function () { + function F() {}; + + return function (obj) { + var subtype; + + F.prototype = obj; + + subtype = new F(); + + F.prototype = null; + + return subtype; + }; + }()) + + /** + * CryptoJS namespace. + */ + var C = {}; + + /** + * Library namespace. + */ + var C_lib = C.lib = {}; + + /** + * Base object for prototypal inheritance. + */ + var Base = C_lib.Base = (function () { + + + return { + /** + * Creates a new object that inherits from this object. + * + * @param {Object} overrides Properties to copy into the new object. + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * field: 'value', + * + * method: function () { + * } + * }); + */ + extend: function (overrides) { + // Spawn + var subtype = create(this); + + // Augment + if (overrides) { + subtype.mixIn(overrides); + } + + // Create default initializer + if (!subtype.hasOwnProperty('init') || this.init === subtype.init) { + subtype.init = function () { + subtype.$super.init.apply(this, arguments); + }; + } + + // Initializer's prototype is the subtype object + subtype.init.prototype = subtype; + + // Reference supertype + subtype.$super = this; + + return subtype; + }, + + /** + * Extends this object and runs the init method. + * Arguments to create() will be passed to init(). + * + * @return {Object} The new object. + * + * @static + * + * @example + * + * var instance = MyType.create(); + */ + create: function () { + var instance = this.extend(); + instance.init.apply(instance, arguments); + + return instance; + }, + + /** + * Initializes a newly created object. + * Override this method to add some logic when your objects are created. + * + * @example + * + * var MyType = CryptoJS.lib.Base.extend({ + * init: function () { + * // ... + * } + * }); + */ + init: function () { + }, + + /** + * Copies properties into this object. + * + * @param {Object} properties The properties to mix in. + * + * @example + * + * MyType.mixIn({ + * field: 'value' + * }); + */ + mixIn: function (properties) { + for (var propertyName in properties) { + if (properties.hasOwnProperty(propertyName)) { + this[propertyName] = properties[propertyName]; + } + } + + // IE won't copy toString using the loop above + if (properties.hasOwnProperty('toString')) { + this.toString = properties.toString; + } + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = instance.clone(); + */ + clone: function () { + return this.init.prototype.extend(this); + } + }; + }()); + + /** + * An array of 32-bit words. + * + * @property {Array} words The array of 32-bit words. + * @property {number} sigBytes The number of significant bytes in this word array. + */ + var WordArray = C_lib.WordArray = Base.extend({ + /** + * Initializes a newly created word array. + * + * @param {Array} words (Optional) An array of 32-bit words. + * @param {number} sigBytes (Optional) The number of significant bytes in the words. + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.create(); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]); + * var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6); + */ + init: function (words, sigBytes) { + words = this.words = words || []; + + if (sigBytes != undefined) { + this.sigBytes = sigBytes; + } else { + this.sigBytes = words.length * 4; + } + }, + + /** + * Converts this word array to a string. + * + * @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex + * + * @return {string} The stringified word array. + * + * @example + * + * var string = wordArray + ''; + * var string = wordArray.toString(); + * var string = wordArray.toString(CryptoJS.enc.Utf8); + */ + toString: function (encoder) { + return (encoder || Hex).stringify(this); + }, + + /** + * Concatenates a word array to this word array. + * + * @param {WordArray} wordArray The word array to append. + * + * @return {WordArray} This word array. + * + * @example + * + * wordArray1.concat(wordArray2); + */ + concat: function (wordArray) { + // Shortcuts + var thisWords = this.words; + var thatWords = wordArray.words; + var thisSigBytes = this.sigBytes; + var thatSigBytes = wordArray.sigBytes; + + // Clamp excess bits + this.clamp(); + + // Concat + if (thisSigBytes % 4) { + // Copy one byte at a time + for (var i = 0; i < thatSigBytes; i++) { + var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8); + } + } else { + // Copy one word at a time + for (var i = 0; i < thatSigBytes; i += 4) { + thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2]; + } + } + this.sigBytes += thatSigBytes; + + // Chainable + return this; + }, + + /** + * Removes insignificant bits. + * + * @example + * + * wordArray.clamp(); + */ + clamp: function () { + // Shortcuts + var words = this.words; + var sigBytes = this.sigBytes; + + // Clamp + words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8); + words.length = Math.ceil(sigBytes / 4); + }, + + /** + * Creates a copy of this word array. + * + * @return {WordArray} The clone. + * + * @example + * + * var clone = wordArray.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone.words = this.words.slice(0); + + return clone; + }, + + /** + * Creates a word array filled with random bytes. + * + * @param {number} nBytes The number of random bytes to generate. + * + * @return {WordArray} The random word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.lib.WordArray.random(16); + */ + random: function (nBytes) { + var words = []; + + var r = (function (m_w) { + var m_w = m_w; + var m_z = 0x3ade68b1; + var mask = 0xffffffff; + + return function () { + m_z = (0x9069 * (m_z & 0xFFFF) + (m_z >> 0x10)) & mask; + m_w = (0x4650 * (m_w & 0xFFFF) + (m_w >> 0x10)) & mask; + var result = ((m_z << 0x10) + m_w) & mask; + result /= 0x100000000; + result += 0.5; + return result * (Math.random() > .5 ? 1 : -1); + } + }); + + for (var i = 0, rcache; i < nBytes; i += 4) { + var _r = r((rcache || Math.random()) * 0x100000000); + + rcache = _r() * 0x3ade67b7; + words.push((_r() * 0x100000000) | 0); + } + + return new WordArray.init(words, nBytes); + } + }); + + /** + * Encoder namespace. + */ + var C_enc = C.enc = {}; + + /** + * Hex encoding strategy. + */ + var Hex = C_enc.Hex = { + /** + * Converts a word array to a hex string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The hex string. + * + * @static + * + * @example + * + * var hexString = CryptoJS.enc.Hex.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var hexChars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + hexChars.push((bite >>> 4).toString(16)); + hexChars.push((bite & 0x0f).toString(16)); + } + + return hexChars.join(''); + }, + + /** + * Converts a hex string to a word array. + * + * @param {string} hexStr The hex string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Hex.parse(hexString); + */ + parse: function (hexStr) { + // Shortcut + var hexStrLength = hexStr.length; + + // Convert + var words = []; + for (var i = 0; i < hexStrLength; i += 2) { + words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4); + } + + return new WordArray.init(words, hexStrLength / 2); + } + }; + + /** + * Latin1 encoding strategy. + */ + var Latin1 = C_enc.Latin1 = { + /** + * Converts a word array to a Latin1 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Latin1 string. + * + * @static + * + * @example + * + * var latin1String = CryptoJS.enc.Latin1.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + + // Convert + var latin1Chars = []; + for (var i = 0; i < sigBytes; i++) { + var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + latin1Chars.push(String.fromCharCode(bite)); + } + + return latin1Chars.join(''); + }, + + /** + * Converts a Latin1 string to a word array. + * + * @param {string} latin1Str The Latin1 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Latin1.parse(latin1String); + */ + parse: function (latin1Str) { + // Shortcut + var latin1StrLength = latin1Str.length; + + // Convert + var words = []; + for (var i = 0; i < latin1StrLength; i++) { + words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8); + } + + return new WordArray.init(words, latin1StrLength); + } + }; + + /** + * UTF-8 encoding strategy. + */ + var Utf8 = C_enc.Utf8 = { + /** + * Converts a word array to a UTF-8 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The UTF-8 string. + * + * @static + * + * @example + * + * var utf8String = CryptoJS.enc.Utf8.stringify(wordArray); + */ + stringify: function (wordArray) { + try { + return decodeURIComponent(escape(Latin1.stringify(wordArray))); + } catch (e) { + throw new Error('Malformed UTF-8 data'); + } + }, + + /** + * Converts a UTF-8 string to a word array. + * + * @param {string} utf8Str The UTF-8 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Utf8.parse(utf8String); + */ + parse: function (utf8Str) { + return Latin1.parse(unescape(encodeURIComponent(utf8Str))); + } + }; + + /** + * Abstract buffered block algorithm template. + * + * The property blockSize must be implemented in a concrete subtype. + * + * @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0 + */ + var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({ + /** + * Resets this block algorithm's data buffer to its initial state. + * + * @example + * + * bufferedBlockAlgorithm.reset(); + */ + reset: function () { + // Initial values + this._data = new WordArray.init(); + this._nDataBytes = 0; + }, + + /** + * Adds new data to this block algorithm's buffer. + * + * @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8. + * + * @example + * + * bufferedBlockAlgorithm._append('data'); + * bufferedBlockAlgorithm._append(wordArray); + */ + _append: function (data) { + // Convert string to WordArray, else assume WordArray already + if (typeof data == 'string') { + data = Utf8.parse(data); + } + + // Append + this._data.concat(data); + this._nDataBytes += data.sigBytes; + }, + + /** + * Processes available data blocks. + * + * This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype. + * + * @param {boolean} doFlush Whether all blocks and partial blocks should be processed. + * + * @return {WordArray} The processed data. + * + * @example + * + * var processedData = bufferedBlockAlgorithm._process(); + * var processedData = bufferedBlockAlgorithm._process(!!'flush'); + */ + _process: function (doFlush) { + // Shortcuts + var data = this._data; + var dataWords = data.words; + var dataSigBytes = data.sigBytes; + var blockSize = this.blockSize; + var blockSizeBytes = blockSize * 4; + + // Count blocks ready + var nBlocksReady = dataSigBytes / blockSizeBytes; + if (doFlush) { + // Round up to include partial blocks + nBlocksReady = Math.ceil(nBlocksReady); + } else { + // Round down to include only full blocks, + // less the number of blocks that must remain in the buffer + nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0); + } + + // Count words ready + var nWordsReady = nBlocksReady * blockSize; + + // Count bytes ready + var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes); + + // Process blocks + if (nWordsReady) { + for (var offset = 0; offset < nWordsReady; offset += blockSize) { + // Perform concrete-algorithm logic + this._doProcessBlock(dataWords, offset); + } + + // Remove processed words + var processedWords = dataWords.splice(0, nWordsReady); + data.sigBytes -= nBytesReady; + } + + // Return processed words + return new WordArray.init(processedWords, nBytesReady); + }, + + /** + * Creates a copy of this object. + * + * @return {Object} The clone. + * + * @example + * + * var clone = bufferedBlockAlgorithm.clone(); + */ + clone: function () { + var clone = Base.clone.call(this); + clone._data = this._data.clone(); + + return clone; + }, + + _minBufferSize: 0 + }); + + /** + * Abstract hasher template. + * + * @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits) + */ + var Hasher = C_lib.Hasher = BufferedBlockAlgorithm.extend({ + /** + * Configuration options. + */ + cfg: Base.extend(), + + /** + * Initializes a newly created hasher. + * + * @param {Object} cfg (Optional) The configuration options to use for this hash computation. + * + * @example + * + * var hasher = CryptoJS.algo.SHA256.create(); + */ + init: function (cfg) { + // Apply config defaults + this.cfg = this.cfg.extend(cfg); + + // Set initial values + this.reset(); + }, + + /** + * Resets this hasher to its initial state. + * + * @example + * + * hasher.reset(); + */ + reset: function () { + // Reset data buffer + BufferedBlockAlgorithm.reset.call(this); + + // Perform concrete-hasher logic + this._doReset(); + }, + + /** + * Updates this hasher with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {Hasher} This hasher. + * + * @example + * + * hasher.update('message'); + * hasher.update(wordArray); + */ + update: function (messageUpdate) { + // Append + this._append(messageUpdate); + + // Update the hash + this._process(); + + // Chainable + return this; + }, + + /** + * Finalizes the hash computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The hash. + * + * @example + * + * var hash = hasher.finalize(); + * var hash = hasher.finalize('message'); + * var hash = hasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Final message update + if (messageUpdate) { + this._append(messageUpdate); + } + + // Perform concrete-hasher logic + var hash = this._doFinalize(); + + return hash; + }, + + blockSize: 512/32, + + /** + * Creates a shortcut function to a hasher's object interface. + * + * @param {Hasher} hasher The hasher to create a helper for. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256); + */ + _createHelper: function (hasher) { + return function (message, cfg) { + return new hasher.init(cfg).finalize(message); + }; + }, + + /** + * Creates a shortcut function to the HMAC's object interface. + * + * @param {Hasher} hasher The hasher to use in this HMAC helper. + * + * @return {Function} The shortcut function. + * + * @static + * + * @example + * + * var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256); + */ + _createHmacHelper: function (hasher) { + return function (message, key) { + return new C_algo.HMAC.init(hasher, key).finalize(message); + }; + } + }); + + /** + * Algorithm namespace. + */ + var C_algo = C.algo = {}; + + return C; + }(Math)); + + + return CryptoJS; + +})); +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/enc-base64.js":[function(require,module,exports){ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var C_enc = C.enc; + + /** + * Base64 encoding strategy. + */ + var Base64 = C_enc.Base64 = { + /** + * Converts a word array to a Base64 string. + * + * @param {WordArray} wordArray The word array. + * + * @return {string} The Base64 string. + * + * @static + * + * @example + * + * var base64String = CryptoJS.enc.Base64.stringify(wordArray); + */ + stringify: function (wordArray) { + // Shortcuts + var words = wordArray.words; + var sigBytes = wordArray.sigBytes; + var map = this._map; + + // Clamp excess bits + wordArray.clamp(); + + // Convert + var base64Chars = []; + for (var i = 0; i < sigBytes; i += 3) { + var byte1 = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff; + var byte2 = (words[(i + 1) >>> 2] >>> (24 - ((i + 1) % 4) * 8)) & 0xff; + var byte3 = (words[(i + 2) >>> 2] >>> (24 - ((i + 2) % 4) * 8)) & 0xff; + + var triplet = (byte1 << 16) | (byte2 << 8) | byte3; + + for (var j = 0; (j < 4) && (i + j * 0.75 < sigBytes); j++) { + base64Chars.push(map.charAt((triplet >>> (6 * (3 - j))) & 0x3f)); + } + } + + // Add padding + var paddingChar = map.charAt(64); + if (paddingChar) { + while (base64Chars.length % 4) { + base64Chars.push(paddingChar); + } + } + + return base64Chars.join(''); + }, + + /** + * Converts a Base64 string to a word array. + * + * @param {string} base64Str The Base64 string. + * + * @return {WordArray} The word array. + * + * @static + * + * @example + * + * var wordArray = CryptoJS.enc.Base64.parse(base64String); + */ + parse: function (base64Str) { + // Shortcuts + var base64StrLength = base64Str.length; + var map = this._map; + var reverseMap = this._reverseMap; + + if (!reverseMap) { + reverseMap = this._reverseMap = []; + for (var j = 0; j < map.length; j++) { + reverseMap[map.charCodeAt(j)] = j; + } + } + + // Ignore padding + var paddingChar = map.charAt(64); + if (paddingChar) { + var paddingIndex = base64Str.indexOf(paddingChar); + if (paddingIndex !== -1) { + base64StrLength = paddingIndex; + } + } + + // Convert + return parseLoop(base64Str, base64StrLength, reverseMap); + + }, + + _map: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=' + }; + + function parseLoop(base64Str, base64StrLength, reverseMap) { + var words = []; + var nBytes = 0; + for (var i = 0; i < base64StrLength; i++) { + if (i % 4) { + var bits1 = reverseMap[base64Str.charCodeAt(i - 1)] << ((i % 4) * 2); + var bits2 = reverseMap[base64Str.charCodeAt(i)] >>> (6 - (i % 4) * 2); + words[nBytes >>> 2] |= (bits1 | bits2) << (24 - (nBytes % 4) * 8); + nBytes++; + } + } + return WordArray.create(words, nBytes); + } + }()); + + + return CryptoJS.enc.Base64; + +})); +},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/enc-hex.js":[function(require,module,exports){ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + return CryptoJS.enc.Hex; + +})); +},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/evpkdf.js":[function(require,module,exports){ +;(function (root, factory, undef) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core"), require("./sha1"), require("./hmac")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core", "./sha1", "./hmac"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var WordArray = C_lib.WordArray; + var C_algo = C.algo; + var MD5 = C_algo.MD5; + + /** + * This key derivation function is meant to conform with EVP_BytesToKey. + * www.openssl.org/docs/crypto/EVP_BytesToKey.html + */ + var EvpKDF = C_algo.EvpKDF = Base.extend({ + /** + * Configuration options. + * + * @property {number} keySize The key size in words to generate. Default: 4 (128 bits) + * @property {Hasher} hasher The hash algorithm to use. Default: MD5 + * @property {number} iterations The number of iterations to perform. Default: 1 + */ + cfg: Base.extend({ + keySize: 128/32, + hasher: MD5, + iterations: 1 + }), + + /** + * Initializes a newly created key derivation function. + * + * @param {Object} cfg (Optional) The configuration options to use for the derivation. + * + * @example + * + * var kdf = CryptoJS.algo.EvpKDF.create(); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8 }); + * var kdf = CryptoJS.algo.EvpKDF.create({ keySize: 8, iterations: 1000 }); + */ + init: function (cfg) { + this.cfg = this.cfg.extend(cfg); + }, + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * + * @return {WordArray} The derived key. + * + * @example + * + * var key = kdf.compute(password, salt); + */ + compute: function (password, salt) { + // Shortcut + var cfg = this.cfg; + + // Init hasher + var hasher = cfg.hasher.create(); + + // Initial values + var derivedKey = WordArray.create(); + + // Shortcuts + var derivedKeyWords = derivedKey.words; + var keySize = cfg.keySize; + var iterations = cfg.iterations; + + // Generate key + while (derivedKeyWords.length < keySize) { + if (block) { + hasher.update(block); + } + var block = hasher.update(password).finalize(salt); + hasher.reset(); + + // Iterations + for (var i = 1; i < iterations; i++) { + block = hasher.finalize(block); + hasher.reset(); + } + + derivedKey.concat(block); + } + derivedKey.sigBytes = keySize * 4; + + return derivedKey; + } + }); + + /** + * Derives a key from a password. + * + * @param {WordArray|string} password The password. + * @param {WordArray|string} salt A salt. + * @param {Object} cfg (Optional) The configuration options to use for this computation. + * + * @return {WordArray} The derived key. + * + * @static + * + * @example + * + * var key = CryptoJS.EvpKDF(password, salt); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8 }); + * var key = CryptoJS.EvpKDF(password, salt, { keySize: 8, iterations: 1000 }); + */ + C.EvpKDF = function (password, salt, cfg) { + return EvpKDF.create(cfg).compute(password, salt); + }; + }()); + + + return CryptoJS.EvpKDF; + +})); +},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js","./hmac":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/hmac.js","./sha1":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/sha1.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/hmac.js":[function(require,module,exports){ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var Base = C_lib.Base; + var C_enc = C.enc; + var Utf8 = C_enc.Utf8; + var C_algo = C.algo; + + /** + * HMAC algorithm. + */ + var HMAC = C_algo.HMAC = Base.extend({ + /** + * Initializes a newly created HMAC. + * + * @param {Hasher} hasher The hash algorithm to use. + * @param {WordArray|string} key The secret key. + * + * @example + * + * var hmacHasher = CryptoJS.algo.HMAC.create(CryptoJS.algo.SHA256, key); + */ + init: function (hasher, key) { + // Init hasher + hasher = this._hasher = new hasher.init(); + + // Convert string to WordArray, else assume WordArray already + if (typeof key == 'string') { + key = Utf8.parse(key); + } + + // Shortcuts + var hasherBlockSize = hasher.blockSize; + var hasherBlockSizeBytes = hasherBlockSize * 4; + + // Allow arbitrary length keys + if (key.sigBytes > hasherBlockSizeBytes) { + key = hasher.finalize(key); + } + + // Clamp excess bits + key.clamp(); + + // Clone key for inner and outer pads + var oKey = this._oKey = key.clone(); + var iKey = this._iKey = key.clone(); + + // Shortcuts + var oKeyWords = oKey.words; + var iKeyWords = iKey.words; + + // XOR keys with pad constants + for (var i = 0; i < hasherBlockSize; i++) { + oKeyWords[i] ^= 0x5c5c5c5c; + iKeyWords[i] ^= 0x36363636; + } + oKey.sigBytes = iKey.sigBytes = hasherBlockSizeBytes; + + // Set initial values + this.reset(); + }, + + /** + * Resets this HMAC to its initial state. + * + * @example + * + * hmacHasher.reset(); + */ + reset: function () { + // Shortcut + var hasher = this._hasher; + + // Reset + hasher.reset(); + hasher.update(this._iKey); + }, + + /** + * Updates this HMAC with a message. + * + * @param {WordArray|string} messageUpdate The message to append. + * + * @return {HMAC} This HMAC instance. + * + * @example + * + * hmacHasher.update('message'); + * hmacHasher.update(wordArray); + */ + update: function (messageUpdate) { + this._hasher.update(messageUpdate); + + // Chainable + return this; + }, + + /** + * Finalizes the HMAC computation. + * Note that the finalize operation is effectively a destructive, read-once operation. + * + * @param {WordArray|string} messageUpdate (Optional) A final message update. + * + * @return {WordArray} The HMAC. + * + * @example + * + * var hmac = hmacHasher.finalize(); + * var hmac = hmacHasher.finalize('message'); + * var hmac = hmacHasher.finalize(wordArray); + */ + finalize: function (messageUpdate) { + // Shortcut + var hasher = this._hasher; + + // Compute HMAC + var innerHash = hasher.finalize(messageUpdate); + hasher.reset(); + var hmac = hasher.finalize(this._oKey.clone().concat(innerHash)); + + return hmac; + } + }); + }()); + + +})); +},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/md5.js":[function(require,module,exports){ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function (Math) { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Constants table + var T = []; + + // Compute constants + (function () { + for (var i = 0; i < 64; i++) { + T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0; + } + }()); + + /** + * MD5 hash algorithm. + */ + var MD5 = C_algo.MD5 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Swap endian + for (var i = 0; i < 16; i++) { + // Shortcuts + var offset_i = offset + i; + var M_offset_i = M[offset_i]; + + M[offset_i] = ( + (((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) | + (((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00) + ); + } + + // Shortcuts + var H = this._hash.words; + + var M_offset_0 = M[offset + 0]; + var M_offset_1 = M[offset + 1]; + var M_offset_2 = M[offset + 2]; + var M_offset_3 = M[offset + 3]; + var M_offset_4 = M[offset + 4]; + var M_offset_5 = M[offset + 5]; + var M_offset_6 = M[offset + 6]; + var M_offset_7 = M[offset + 7]; + var M_offset_8 = M[offset + 8]; + var M_offset_9 = M[offset + 9]; + var M_offset_10 = M[offset + 10]; + var M_offset_11 = M[offset + 11]; + var M_offset_12 = M[offset + 12]; + var M_offset_13 = M[offset + 13]; + var M_offset_14 = M[offset + 14]; + var M_offset_15 = M[offset + 15]; + + // Working varialbes + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + + // Computation + a = FF(a, b, c, d, M_offset_0, 7, T[0]); + d = FF(d, a, b, c, M_offset_1, 12, T[1]); + c = FF(c, d, a, b, M_offset_2, 17, T[2]); + b = FF(b, c, d, a, M_offset_3, 22, T[3]); + a = FF(a, b, c, d, M_offset_4, 7, T[4]); + d = FF(d, a, b, c, M_offset_5, 12, T[5]); + c = FF(c, d, a, b, M_offset_6, 17, T[6]); + b = FF(b, c, d, a, M_offset_7, 22, T[7]); + a = FF(a, b, c, d, M_offset_8, 7, T[8]); + d = FF(d, a, b, c, M_offset_9, 12, T[9]); + c = FF(c, d, a, b, M_offset_10, 17, T[10]); + b = FF(b, c, d, a, M_offset_11, 22, T[11]); + a = FF(a, b, c, d, M_offset_12, 7, T[12]); + d = FF(d, a, b, c, M_offset_13, 12, T[13]); + c = FF(c, d, a, b, M_offset_14, 17, T[14]); + b = FF(b, c, d, a, M_offset_15, 22, T[15]); + + a = GG(a, b, c, d, M_offset_1, 5, T[16]); + d = GG(d, a, b, c, M_offset_6, 9, T[17]); + c = GG(c, d, a, b, M_offset_11, 14, T[18]); + b = GG(b, c, d, a, M_offset_0, 20, T[19]); + a = GG(a, b, c, d, M_offset_5, 5, T[20]); + d = GG(d, a, b, c, M_offset_10, 9, T[21]); + c = GG(c, d, a, b, M_offset_15, 14, T[22]); + b = GG(b, c, d, a, M_offset_4, 20, T[23]); + a = GG(a, b, c, d, M_offset_9, 5, T[24]); + d = GG(d, a, b, c, M_offset_14, 9, T[25]); + c = GG(c, d, a, b, M_offset_3, 14, T[26]); + b = GG(b, c, d, a, M_offset_8, 20, T[27]); + a = GG(a, b, c, d, M_offset_13, 5, T[28]); + d = GG(d, a, b, c, M_offset_2, 9, T[29]); + c = GG(c, d, a, b, M_offset_7, 14, T[30]); + b = GG(b, c, d, a, M_offset_12, 20, T[31]); + + a = HH(a, b, c, d, M_offset_5, 4, T[32]); + d = HH(d, a, b, c, M_offset_8, 11, T[33]); + c = HH(c, d, a, b, M_offset_11, 16, T[34]); + b = HH(b, c, d, a, M_offset_14, 23, T[35]); + a = HH(a, b, c, d, M_offset_1, 4, T[36]); + d = HH(d, a, b, c, M_offset_4, 11, T[37]); + c = HH(c, d, a, b, M_offset_7, 16, T[38]); + b = HH(b, c, d, a, M_offset_10, 23, T[39]); + a = HH(a, b, c, d, M_offset_13, 4, T[40]); + d = HH(d, a, b, c, M_offset_0, 11, T[41]); + c = HH(c, d, a, b, M_offset_3, 16, T[42]); + b = HH(b, c, d, a, M_offset_6, 23, T[43]); + a = HH(a, b, c, d, M_offset_9, 4, T[44]); + d = HH(d, a, b, c, M_offset_12, 11, T[45]); + c = HH(c, d, a, b, M_offset_15, 16, T[46]); + b = HH(b, c, d, a, M_offset_2, 23, T[47]); + + a = II(a, b, c, d, M_offset_0, 6, T[48]); + d = II(d, a, b, c, M_offset_7, 10, T[49]); + c = II(c, d, a, b, M_offset_14, 15, T[50]); + b = II(b, c, d, a, M_offset_5, 21, T[51]); + a = II(a, b, c, d, M_offset_12, 6, T[52]); + d = II(d, a, b, c, M_offset_3, 10, T[53]); + c = II(c, d, a, b, M_offset_10, 15, T[54]); + b = II(b, c, d, a, M_offset_1, 21, T[55]); + a = II(a, b, c, d, M_offset_8, 6, T[56]); + d = II(d, a, b, c, M_offset_15, 10, T[57]); + c = II(c, d, a, b, M_offset_6, 15, T[58]); + b = II(b, c, d, a, M_offset_13, 21, T[59]); + a = II(a, b, c, d, M_offset_4, 6, T[60]); + d = II(d, a, b, c, M_offset_11, 10, T[61]); + c = II(c, d, a, b, M_offset_2, 15, T[62]); + b = II(b, c, d, a, M_offset_9, 21, T[63]); + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + + var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000); + var nBitsTotalL = nBitsTotal; + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = ( + (((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) | + (((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00) + ); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = ( + (((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) | + (((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00) + ); + + data.sigBytes = (dataWords.length + 1) * 4; + + // Hash final blocks + this._process(); + + // Shortcuts + var hash = this._hash; + var H = hash.words; + + // Swap endian + for (var i = 0; i < 4; i++) { + // Shortcut + var H_i = H[i]; + + H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | + (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00); + } + + // Return final computed hash + return hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + function FF(a, b, c, d, x, s, t) { + var n = a + ((b & c) | (~b & d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function GG(a, b, c, d, x, s, t) { + var n = a + ((b & d) | (c & ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function HH(a, b, c, d, x, s, t) { + var n = a + (b ^ c ^ d) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + function II(a, b, c, d, x, s, t) { + var n = a + (c ^ (b | ~d)) + x + t; + return ((n << s) | (n >>> (32 - s))) + b; + } + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.MD5('message'); + * var hash = CryptoJS.MD5(wordArray); + */ + C.MD5 = Hasher._createHelper(MD5); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacMD5(message, key); + */ + C.HmacMD5 = Hasher._createHmacHelper(MD5); + }(Math)); + + + return CryptoJS.MD5; + +})); +},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/sha1.js":[function(require,module,exports){ +;(function (root, factory) { + if (typeof exports === "object") { + // CommonJS + module.exports = exports = factory(require("./core")); + } + else if (typeof define === "function" && define.amd) { + // AMD + define(["./core"], factory); + } + else { + // Global (browser) + factory(root.CryptoJS); + } +}(this, function (CryptoJS) { + + (function () { + // Shortcuts + var C = CryptoJS; + var C_lib = C.lib; + var WordArray = C_lib.WordArray; + var Hasher = C_lib.Hasher; + var C_algo = C.algo; + + // Reusable object + var W = []; + + /** + * SHA-1 hash algorithm. + */ + var SHA1 = C_algo.SHA1 = Hasher.extend({ + _doReset: function () { + this._hash = new WordArray.init([ + 0x67452301, 0xefcdab89, + 0x98badcfe, 0x10325476, + 0xc3d2e1f0 + ]); + }, + + _doProcessBlock: function (M, offset) { + // Shortcut + var H = this._hash.words; + + // Working variables + var a = H[0]; + var b = H[1]; + var c = H[2]; + var d = H[3]; + var e = H[4]; + + // Computation + for (var i = 0; i < 80; i++) { + if (i < 16) { + W[i] = M[offset + i] | 0; + } else { + var n = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]; + W[i] = (n << 1) | (n >>> 31); + } + + var t = ((a << 5) | (a >>> 27)) + e + W[i]; + if (i < 20) { + t += ((b & c) | (~b & d)) + 0x5a827999; + } else if (i < 40) { + t += (b ^ c ^ d) + 0x6ed9eba1; + } else if (i < 60) { + t += ((b & c) | (b & d) | (c & d)) - 0x70e44324; + } else /* if (i < 80) */ { + t += (b ^ c ^ d) - 0x359d3e2a; + } + + e = d; + d = c; + c = (b << 30) | (b >>> 2); + b = a; + a = t; + } + + // Intermediate hash value + H[0] = (H[0] + a) | 0; + H[1] = (H[1] + b) | 0; + H[2] = (H[2] + c) | 0; + H[3] = (H[3] + d) | 0; + H[4] = (H[4] + e) | 0; + }, + + _doFinalize: function () { + // Shortcuts + var data = this._data; + var dataWords = data.words; + + var nBitsTotal = this._nDataBytes * 8; + var nBitsLeft = data.sigBytes * 8; + + // Add padding + dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000); + dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal; + data.sigBytes = dataWords.length * 4; + + // Hash final blocks + this._process(); + + // Return final computed hash + return this._hash; + }, + + clone: function () { + var clone = Hasher.clone.call(this); + clone._hash = this._hash.clone(); + + return clone; + } + }); + + /** + * Shortcut function to the hasher's object interface. + * + * @param {WordArray|string} message The message to hash. + * + * @return {WordArray} The hash. + * + * @static + * + * @example + * + * var hash = CryptoJS.SHA1('message'); + * var hash = CryptoJS.SHA1(wordArray); + */ + C.SHA1 = Hasher._createHelper(SHA1); + + /** + * Shortcut function to the HMAC's object interface. + * + * @param {WordArray|string} message The message to hash. + * @param {WordArray|string} key The secret key. + * + * @return {WordArray} The HMAC. + * + * @static + * + * @example + * + * var hmac = CryptoJS.HmacSHA1(message, key); + */ + C.HmacSHA1 = Hasher._createHmacHelper(SHA1); + }()); + + + return CryptoJS.SHA1; + +})); +},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/index.js":[function(require,module,exports){ +var pSlice = Array.prototype.slice; +var objectKeys = require('./lib/keys.js'); +var isArguments = require('./lib/is_arguments.js'); + +var deepEqual = module.exports = function (actual, expected, opts) { + if (!opts) opts = {}; + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (actual instanceof Date && expected instanceof Date) { + return actual.getTime() === expected.getTime(); + + // 7.3. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (!actual || !expected || typeof actual != 'object' && typeof expected != 'object') { + return opts.strict ? actual === expected : actual == expected; + + // 7.4. For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected, opts); + } +} + +function isUndefinedOrNull(value) { + return value === null || value === undefined; +} + +function isBuffer (x) { + if (!x || typeof x !== 'object' || typeof x.length !== 'number') return false; + if (typeof x.copy !== 'function' || typeof x.slice !== 'function') { + return false; + } + if (x.length > 0 && typeof x[0] !== 'number') return false; + return true; +} + +function objEquiv(a, b, opts) { + var i, key; + if (isUndefinedOrNull(a) || isUndefinedOrNull(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return deepEqual(a, b, opts); + } + if (isBuffer(a)) { + if (!isBuffer(b)) { + return false; + } + if (a.length !== b.length) return false; + for (i = 0; i < a.length; i++) { + if (a[i] !== b[i]) return false; + } + return true; + } + try { + var ka = objectKeys(a), + kb = objectKeys(b); + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!deepEqual(a[key], b[key], opts)) return false; + } + return typeof a === typeof b; +} + +},{"./lib/is_arguments.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/lib/is_arguments.js","./lib/keys.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/lib/keys.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/lib/is_arguments.js":[function(require,module,exports){ +var supportsArgumentsClass = (function(){ + return Object.prototype.toString.call(arguments) +})() == '[object Arguments]'; + +exports = module.exports = supportsArgumentsClass ? supported : unsupported; + +exports.supported = supported; +function supported(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +}; + +exports.unsupported = unsupported; +function unsupported(object){ + return object && + typeof object == 'object' && + typeof object.length == 'number' && + Object.prototype.hasOwnProperty.call(object, 'callee') && + !Object.prototype.propertyIsEnumerable.call(object, 'callee') || + false; +}; + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/lib/keys.js":[function(require,module,exports){ +exports = module.exports = typeof Object.keys === 'function' + ? Object.keys : shim; + +exports.shim = shim; +function shim (obj) { + var keys = []; + for (var key in obj) keys.push(key); + return keys; +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/curve.js":[function(require,module,exports){ +var assert = require('assert') +var BigInteger = require('bigi') + +var Point = require('./point') + +function Curve (p, a, b, Gx, Gy, n, h) { + this.p = p + this.a = a + this.b = b + this.G = Point.fromAffine(this, Gx, Gy) + this.n = n + this.h = h + + this.infinity = new Point(this, null, null, BigInteger.ZERO) + + // result caching + this.pOverFour = p.add(BigInteger.ONE).shiftRight(2) + + // determine size of p in bytes + this.pLength = Math.floor((this.p.bitLength() + 7) / 8) +} + +Curve.prototype.pointFromX = function (isOdd, x) { + var alpha = x.pow(3).add(this.a.multiply(x)).add(this.b).mod(this.p) + var beta = alpha.modPow(this.pOverFour, this.p) // XXX: not compatible with all curves + + var y = beta + if (beta.isEven() ^ !isOdd) { + y = this.p.subtract(y) // -y % p + } + + return Point.fromAffine(this, x, y) +} + +Curve.prototype.isInfinity = function (Q) { + if (Q === this.infinity) return true + + return Q.z.signum() === 0 && Q.y.signum() !== 0 +} + +Curve.prototype.isOnCurve = function (Q) { + if (this.isInfinity(Q)) return true + + var x = Q.affineX + var y = Q.affineY + var a = this.a + var b = this.b + var p = this.p + + // Check that xQ and yQ are integers in the interval [0, p - 1] + if (x.signum() < 0 || x.compareTo(p) >= 0) return false + if (y.signum() < 0 || y.compareTo(p) >= 0) return false + + // and check that y^2 = x^3 + ax + b (mod p) + var lhs = y.square().mod(p) + var rhs = x.pow(3).add(a.multiply(x)).add(b).mod(p) + return lhs.equals(rhs) +} + +/** + * Validate an elliptic curve point. + * + * See SEC 1, section 3.2.2.1: Elliptic Curve Public Key Validation Primitive + */ +Curve.prototype.validate = function (Q) { + // Check Q != O + assert(!this.isInfinity(Q), 'Point is at infinity') + assert(this.isOnCurve(Q), 'Point is not on the curve') + + // Check nQ = O (where Q is a scalar multiple of G) + var nQ = Q.multiply(this.n) + assert(this.isInfinity(nQ), 'Point is not a scalar multiple of G') + + return true +} + +module.exports = Curve + +},{"./point":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/point.js","assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/curves.json":[function(require,module,exports){ +module.exports={ + "secp128r1": { + "p": "fffffffdffffffffffffffffffffffff", + "a": "fffffffdfffffffffffffffffffffffc", + "b": "e87579c11079f43dd824993c2cee5ed3", + "n": "fffffffe0000000075a30d1b9038a115", + "h": "01", + "Gx": "161ff7528b899b2d0c28607ca52c5b86", + "Gy": "cf5ac8395bafeb13c02da292dded7a83" + }, + "secp160k1": { + "p": "fffffffffffffffffffffffffffffffeffffac73", + "a": "00", + "b": "07", + "n": "0100000000000000000001b8fa16dfab9aca16b6b3", + "h": "01", + "Gx": "3b4c382ce37aa192a4019e763036f4f5dd4d7ebb", + "Gy": "938cf935318fdced6bc28286531733c3f03c4fee" + }, + "secp160r1": { + "p": "ffffffffffffffffffffffffffffffff7fffffff", + "a": "ffffffffffffffffffffffffffffffff7ffffffc", + "b": "1c97befc54bd7a8b65acf89f81d4d4adc565fa45", + "n": "0100000000000000000001f4c8f927aed3ca752257", + "h": "01", + "Gx": "4a96b5688ef573284664698968c38bb913cbfc82", + "Gy": "23a628553168947d59dcc912042351377ac5fb32" + }, + "secp192k1": { + "p": "fffffffffffffffffffffffffffffffffffffffeffffee37", + "a": "00", + "b": "03", + "n": "fffffffffffffffffffffffe26f2fc170f69466a74defd8d", + "h": "01", + "Gx": "db4ff10ec057e9ae26b07d0280b7f4341da5d1b1eae06c7d", + "Gy": "9b2f2f6d9c5628a7844163d015be86344082aa88d95e2f9d" + }, + "secp192r1": { + "p": "fffffffffffffffffffffffffffffffeffffffffffffffff", + "a": "fffffffffffffffffffffffffffffffefffffffffffffffc", + "b": "64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1", + "n": "ffffffffffffffffffffffff99def836146bc9b1b4d22831", + "h": "01", + "Gx": "188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012", + "Gy": "07192b95ffc8da78631011ed6b24cdd573f977a11e794811" + }, + "secp256k1": { + "p": "fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", + "a": "00", + "b": "07", + "n": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", + "h": "01", + "Gx": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", + "Gy": "483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8" + }, + "secp256r1": { + "p": "ffffffff00000001000000000000000000000000ffffffffffffffffffffffff", + "a": "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", + "b": "5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b", + "n": "ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", + "h": "01", + "Gx": "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", + "Gy": "4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5" + } +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/index.js":[function(require,module,exports){ +var Point = require('./point') +var Curve = require('./curve') + +var getCurveByName = require('./names') + +module.exports = { + Curve: Curve, + Point: Point, + getCurveByName: getCurveByName +} + +},{"./curve":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/curve.js","./names":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/names.js","./point":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/point.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/names.js":[function(require,module,exports){ +var BigInteger = require('bigi') + +var curves = require('./curves.json') +var Curve = require('./curve') + +function getCurveByName (name) { + var curve = curves[name] + if (!curve) return null + + var p = new BigInteger(curve.p, 16) + var a = new BigInteger(curve.a, 16) + var b = new BigInteger(curve.b, 16) + var n = new BigInteger(curve.n, 16) + var h = new BigInteger(curve.h, 16) + var Gx = new BigInteger(curve.Gx, 16) + var Gy = new BigInteger(curve.Gy, 16) + + return new Curve(p, a, b, Gx, Gy, n, h) +} + +module.exports = getCurveByName + +},{"./curve":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/curve.js","./curves.json":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/curves.json","bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ecurve/lib/point.js":[function(require,module,exports){ +var assert = require('assert') +var Buffer = require('safe-buffer').Buffer +var BigInteger = require('bigi') + +var THREE = BigInteger.valueOf(3) + +function Point (curve, x, y, z) { + assert.notStrictEqual(z, undefined, 'Missing Z coordinate') + + this.curve = curve + this.x = x + this.y = y + this.z = z + this._zInv = null + + this.compressed = true +} + +Object.defineProperty(Point.prototype, 'zInv', { + get: function () { + if (this._zInv === null) { + this._zInv = this.z.modInverse(this.curve.p) + } + + return this._zInv + } +}) + +Object.defineProperty(Point.prototype, 'affineX', { + get: function () { + return this.x.multiply(this.zInv).mod(this.curve.p) + } +}) + +Object.defineProperty(Point.prototype, 'affineY', { + get: function () { + return this.y.multiply(this.zInv).mod(this.curve.p) + } +}) + +Point.fromAffine = function (curve, x, y) { + return new Point(curve, x, y, BigInteger.ONE) +} + +Point.prototype.equals = function (other) { + if (other === this) return true + if (this.curve.isInfinity(this)) return this.curve.isInfinity(other) + if (this.curve.isInfinity(other)) return this.curve.isInfinity(this) + + // u = Y2 * Z1 - Y1 * Z2 + var u = other.y.multiply(this.z).subtract(this.y.multiply(other.z)).mod(this.curve.p) + + if (u.signum() !== 0) return false + + // v = X2 * Z1 - X1 * Z2 + var v = other.x.multiply(this.z).subtract(this.x.multiply(other.z)).mod(this.curve.p) + + return v.signum() === 0 +} + +Point.prototype.negate = function () { + var y = this.curve.p.subtract(this.y) + + return new Point(this.curve, this.x, y, this.z) +} + +Point.prototype.add = function (b) { + if (this.curve.isInfinity(this)) return b + if (this.curve.isInfinity(b)) return this + + var x1 = this.x + var y1 = this.y + var x2 = b.x + var y2 = b.y + + // u = Y2 * Z1 - Y1 * Z2 + var u = y2.multiply(this.z).subtract(y1.multiply(b.z)).mod(this.curve.p) + // v = X2 * Z1 - X1 * Z2 + var v = x2.multiply(this.z).subtract(x1.multiply(b.z)).mod(this.curve.p) + + if (v.signum() === 0) { + if (u.signum() === 0) { + return this.twice() // this == b, so double + } + + return this.curve.infinity // this = -b, so infinity + } + + var v2 = v.square() + var v3 = v2.multiply(v) + var x1v2 = x1.multiply(v2) + var zu2 = u.square().multiply(this.z) + + // x3 = v * (z2 * (z1 * u^2 - 2 * x1 * v^2) - v^3) + var x3 = zu2.subtract(x1v2.shiftLeft(1)).multiply(b.z).subtract(v3).multiply(v).mod(this.curve.p) + // y3 = z2 * (3 * x1 * u * v^2 - y1 * v^3 - z1 * u^3) + u * v^3 + var y3 = x1v2.multiply(THREE).multiply(u).subtract(y1.multiply(v3)).subtract(zu2.multiply(u)).multiply(b.z).add(u.multiply(v3)).mod(this.curve.p) + // z3 = v^3 * z1 * z2 + var z3 = v3.multiply(this.z).multiply(b.z).mod(this.curve.p) + + return new Point(this.curve, x3, y3, z3) +} + +Point.prototype.twice = function () { + if (this.curve.isInfinity(this)) return this + if (this.y.signum() === 0) return this.curve.infinity + + var x1 = this.x + var y1 = this.y + + var y1z1 = y1.multiply(this.z).mod(this.curve.p) + var y1sqz1 = y1z1.multiply(y1).mod(this.curve.p) + var a = this.curve.a + + // w = 3 * x1^2 + a * z1^2 + var w = x1.square().multiply(THREE) + + if (a.signum() !== 0) { + w = w.add(this.z.square().multiply(a)) + } + + w = w.mod(this.curve.p) + // x3 = 2 * y1 * z1 * (w^2 - 8 * x1 * y1^2 * z1) + var x3 = w.square().subtract(x1.shiftLeft(3).multiply(y1sqz1)).shiftLeft(1).multiply(y1z1).mod(this.curve.p) + // y3 = 4 * y1^2 * z1 * (3 * w * x1 - 2 * y1^2 * z1) - w^3 + var y3 = w.multiply(THREE).multiply(x1).subtract(y1sqz1.shiftLeft(1)).shiftLeft(2).multiply(y1sqz1).subtract(w.pow(3)).mod(this.curve.p) + // z3 = 8 * (y1 * z1)^3 + var z3 = y1z1.pow(3).shiftLeft(3).mod(this.curve.p) + + return new Point(this.curve, x3, y3, z3) +} + +// Simple NAF (Non-Adjacent Form) multiplication algorithm +// TODO: modularize the multiplication algorithm +Point.prototype.multiply = function (k) { + if (this.curve.isInfinity(this)) return this + if (k.signum() === 0) return this.curve.infinity + + var e = k + var h = e.multiply(THREE) + + var neg = this.negate() + var R = this + + for (var i = h.bitLength() - 2; i > 0; --i) { + var hBit = h.testBit(i) + var eBit = e.testBit(i) + + R = R.twice() + + if (hBit !== eBit) { + R = R.add(hBit ? this : neg) + } + } + + return R +} + +// Compute this*j + x*k (simultaneous multiplication) +Point.prototype.multiplyTwo = function (j, x, k) { + var i = Math.max(j.bitLength(), k.bitLength()) - 1 + var R = this.curve.infinity + var both = this.add(x) + + while (i >= 0) { + var jBit = j.testBit(i) + var kBit = k.testBit(i) + + R = R.twice() + + if (jBit) { + if (kBit) { + R = R.add(both) + } else { + R = R.add(this) + } + } else if (kBit) { + R = R.add(x) + } + --i + } + + return R +} + +Point.prototype.getEncoded = function (compressed) { + if (compressed == null) compressed = this.compressed + if (this.curve.isInfinity(this)) return Buffer.alloc(1, 0) // Infinity point encoded is simply '00' + + var x = this.affineX + var y = this.affineY + var byteLength = this.curve.pLength + var buffer + + // 0x02/0x03 | X + if (compressed) { + buffer = Buffer.allocUnsafe(1 + byteLength) + buffer.writeUInt8(y.isEven() ? 0x02 : 0x03, 0) + + // 0x04 | X | Y + } else { + buffer = Buffer.allocUnsafe(1 + byteLength + byteLength) + buffer.writeUInt8(0x04, 0) + + y.toBuffer(byteLength).copy(buffer, 1 + byteLength) + } + + x.toBuffer(byteLength).copy(buffer, 1) + + return buffer +} + +Point.decodeFrom = function (curve, buffer) { + var type = buffer.readUInt8(0) + var compressed = (type !== 4) + + var byteLength = Math.floor((curve.p.bitLength() + 7) / 8) + var x = BigInteger.fromBuffer(buffer.slice(1, 1 + byteLength)) + + var Q + if (compressed) { + assert.equal(buffer.length, byteLength + 1, 'Invalid sequence length') + assert(type === 0x02 || type === 0x03, 'Invalid sequence tag') + + var isOdd = (type === 0x03) + Q = curve.pointFromX(isOdd, x) + } else { + assert.equal(buffer.length, 1 + byteLength + byteLength, 'Invalid sequence length') + + var y = BigInteger.fromBuffer(buffer.slice(1 + byteLength)) + Q = Point.fromAffine(curve, x, y) + } + + Q.compressed = compressed + return Q +} + +Point.prototype.toString = function () { + if (this.curve.isInfinity(this)) return '(INFINITY)' + + return '(' + this.affineX.toString() + ',' + this.affineY.toString() + ')' +} + +module.exports = Point + +},{"assert":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/assert/assert.js","bigi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/index.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/events/events.js":[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +function EventEmitter() { + this._events = this._events || {}; + this._maxListeners = this._maxListeners || undefined; +} +module.exports = EventEmitter; + +// Backwards-compat with node 0.10.x +EventEmitter.EventEmitter = EventEmitter; + +EventEmitter.prototype._events = undefined; +EventEmitter.prototype._maxListeners = undefined; + +// By default EventEmitters will print a warning if more than 10 listeners are +// added to it. This is a useful default which helps finding memory leaks. +EventEmitter.defaultMaxListeners = 10; + +// Obviously not all Emitters should be limited to 10. This function allows +// that to be increased. Set to zero for unlimited. +EventEmitter.prototype.setMaxListeners = function(n) { + if (!isNumber(n) || n < 0 || isNaN(n)) + throw TypeError('n must be a positive number'); + this._maxListeners = n; + return this; +}; + +EventEmitter.prototype.emit = function(type) { + var er, handler, len, args, i, listeners; + + if (!this._events) + this._events = {}; + + // If there is no 'error' event listener then throw. + if (type === 'error') { + if (!this._events.error || + (isObject(this._events.error) && !this._events.error.length)) { + er = arguments[1]; + if (er instanceof Error) { + throw er; // Unhandled 'error' event + } else { + // At least give some kind of context to the user + var err = new Error('Uncaught, unspecified "error" event. (' + er + ')'); + err.context = er; + throw err; + } + } + } + + handler = this._events[type]; + + if (isUndefined(handler)) + return false; + + if (isFunction(handler)) { + switch (arguments.length) { + // fast cases + case 1: + handler.call(this); + break; + case 2: + handler.call(this, arguments[1]); + break; + case 3: + handler.call(this, arguments[1], arguments[2]); + break; + // slower + default: + args = Array.prototype.slice.call(arguments, 1); + handler.apply(this, args); + } + } else if (isObject(handler)) { + args = Array.prototype.slice.call(arguments, 1); + listeners = handler.slice(); + len = listeners.length; + for (i = 0; i < len; i++) + listeners[i].apply(this, args); + } + + return true; +}; + +EventEmitter.prototype.addListener = function(type, listener) { + var m; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events) + this._events = {}; + + // To avoid recursion in the case that type === "newListener"! Before + // adding it to the listeners, first emit "newListener". + if (this._events.newListener) + this.emit('newListener', type, + isFunction(listener.listener) ? + listener.listener : listener); + + if (!this._events[type]) + // Optimize the case of one listener. Don't need the extra array object. + this._events[type] = listener; + else if (isObject(this._events[type])) + // If we've already got an array, just append. + this._events[type].push(listener); + else + // Adding the second element, need to change to array. + this._events[type] = [this._events[type], listener]; + + // Check for listener leak + if (isObject(this._events[type]) && !this._events[type].warned) { + if (!isUndefined(this._maxListeners)) { + m = this._maxListeners; + } else { + m = EventEmitter.defaultMaxListeners; + } + + if (m && m > 0 && this._events[type].length > m) { + this._events[type].warned = true; + console.error('(node) warning: possible EventEmitter memory ' + + 'leak detected. %d listeners added. ' + + 'Use emitter.setMaxListeners() to increase limit.', + this._events[type].length); + if (typeof console.trace === 'function') { + // not supported in IE 10 + console.trace(); + } + } + } + + return this; +}; + +EventEmitter.prototype.on = EventEmitter.prototype.addListener; + +EventEmitter.prototype.once = function(type, listener) { + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + var fired = false; + + function g() { + this.removeListener(type, g); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + } + + g.listener = listener; + this.on(type, g); + + return this; +}; + +// emits a 'removeListener' event iff the listener was removed +EventEmitter.prototype.removeListener = function(type, listener) { + var list, position, length, i; + + if (!isFunction(listener)) + throw TypeError('listener must be a function'); + + if (!this._events || !this._events[type]) + return this; + + list = this._events[type]; + length = list.length; + position = -1; + + if (list === listener || + (isFunction(list.listener) && list.listener === listener)) { + delete this._events[type]; + if (this._events.removeListener) + this.emit('removeListener', type, listener); + + } else if (isObject(list)) { + for (i = length; i-- > 0;) { + if (list[i] === listener || + (list[i].listener && list[i].listener === listener)) { + position = i; + break; + } + } + + if (position < 0) + return this; + + if (list.length === 1) { + list.length = 0; + delete this._events[type]; + } else { + list.splice(position, 1); + } + + if (this._events.removeListener) + this.emit('removeListener', type, listener); + } + + return this; +}; + +EventEmitter.prototype.removeAllListeners = function(type) { + var key, listeners; + + if (!this._events) + return this; + + // not listening for removeListener, no need to emit + if (!this._events.removeListener) { + if (arguments.length === 0) + this._events = {}; + else if (this._events[type]) + delete this._events[type]; + return this; + } + + // emit removeListener for all listeners on all events + if (arguments.length === 0) { + for (key in this._events) { + if (key === 'removeListener') continue; + this.removeAllListeners(key); + } + this.removeAllListeners('removeListener'); + this._events = {}; + return this; + } + + listeners = this._events[type]; + + if (isFunction(listeners)) { + this.removeListener(type, listeners); + } else if (listeners) { + // LIFO order + while (listeners.length) + this.removeListener(type, listeners[listeners.length - 1]); + } + delete this._events[type]; + + return this; +}; + +EventEmitter.prototype.listeners = function(type) { + var ret; + if (!this._events || !this._events[type]) + ret = []; + else if (isFunction(this._events[type])) + ret = [this._events[type]]; + else + ret = this._events[type].slice(); + return ret; +}; + +EventEmitter.prototype.listenerCount = function(type) { + if (this._events) { + var evlistener = this._events[type]; + + if (isFunction(evlistener)) + return 1; + else if (evlistener) + return evlistener.length; + } + return 0; +}; + +EventEmitter.listenerCount = function(emitter, type) { + return emitter.listenerCount(type); +}; + +function isFunction(arg) { + return typeof arg === 'function'; +} + +function isNumber(arg) { + return typeof arg === 'number'; +} + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} + +function isUndefined(arg) { + return arg === void 0; +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/hash-base/index.js":[function(require,module,exports){ +'use strict' +var Buffer = require('safe-buffer').Buffer +var Transform = require('stream').Transform +var inherits = require('inherits') + +function throwIfNotStringOrBuffer (val, prefix) { + if (!Buffer.isBuffer(val) && typeof val !== 'string') { + throw new TypeError(prefix + ' must be a string or a buffer') + } +} + +function HashBase (blockSize) { + Transform.call(this) + + this._block = Buffer.allocUnsafe(blockSize) + this._blockSize = blockSize + this._blockOffset = 0 + this._length = [0, 0, 0, 0] + + this._finalized = false +} + +inherits(HashBase, Transform) + +HashBase.prototype._transform = function (chunk, encoding, callback) { + var error = null + try { + this.update(chunk, encoding) + } catch (err) { + error = err + } + + callback(error) +} + +HashBase.prototype._flush = function (callback) { + var error = null + try { + this.push(this.digest()) + } catch (err) { + error = err + } + + callback(error) +} + +HashBase.prototype.update = function (data, encoding) { + throwIfNotStringOrBuffer(data, 'Data') + if (this._finalized) throw new Error('Digest already called') + if (!Buffer.isBuffer(data)) data = Buffer.from(data, encoding) + + // consume data + var block = this._block + var offset = 0 + while (this._blockOffset + data.length - offset >= this._blockSize) { + for (var i = this._blockOffset; i < this._blockSize;) block[i++] = data[offset++] + this._update() + this._blockOffset = 0 + } + while (offset < data.length) block[this._blockOffset++] = data[offset++] + + // update length + for (var j = 0, carry = data.length * 8; carry > 0; ++j) { + this._length[j] += carry + carry = (this._length[j] / 0x0100000000) | 0 + if (carry > 0) this._length[j] -= 0x0100000000 * carry + } + + return this +} + +HashBase.prototype._update = function () { + throw new Error('_update is not implemented') +} + +HashBase.prototype.digest = function (encoding) { + if (this._finalized) throw new Error('Digest already called') + this._finalized = true + + var digest = this._digest() + if (encoding !== undefined) digest = digest.toString(encoding) + + // reset state + this._block.fill(0) + this._blockOffset = 0 + for (var i = 0; i < 4; ++i) this._length[i] = 0 + + return digest +} + +HashBase.prototype._digest = function () { + throw new Error('_digest is not implemented') +} + +module.exports = HashBase + +},{"inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js","stream":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/stream-browserify/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ieee754/index.js":[function(require,module,exports){ +exports.read = function (buffer, offset, isLE, mLen, nBytes) { + var e, m + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var nBits = -7 + var i = isLE ? (nBytes - 1) : 0 + var d = isLE ? -1 : 1 + var s = buffer[offset + i] + + i += d + + e = s & ((1 << (-nBits)) - 1) + s >>= (-nBits) + nBits += eLen + for (; nBits > 0; e = (e * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + m = e & ((1 << (-nBits)) - 1) + e >>= (-nBits) + nBits += mLen + for (; nBits > 0; m = (m * 256) + buffer[offset + i], i += d, nBits -= 8) {} + + if (e === 0) { + e = 1 - eBias + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity) + } else { + m = m + Math.pow(2, mLen) + e = e - eBias + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen) +} + +exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { + var e, m, c + var eLen = (nBytes * 8) - mLen - 1 + var eMax = (1 << eLen) - 1 + var eBias = eMax >> 1 + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) + var i = isLE ? 0 : (nBytes - 1) + var d = isLE ? 1 : -1 + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + + value = Math.abs(value) + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0 + e = eMax + } else { + e = Math.floor(Math.log(value) / Math.LN2) + if (value * (c = Math.pow(2, -e)) < 1) { + e-- + c *= 2 + } + if (e + eBias >= 1) { + value += rt / c + } else { + value += rt * Math.pow(2, 1 - eBias) + } + if (value * c >= 2) { + e++ + c /= 2 + } + + if (e + eBias >= eMax) { + m = 0 + e = eMax + } else if (e + eBias >= 1) { + m = ((value * c) - 1) * Math.pow(2, mLen) + e = e + eBias + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + e = 0 + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} + + e = (e << mLen) | m + eLen += mLen + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} + + buffer[offset + i - d] |= s * 128 +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js":[function(require,module,exports){ +if (typeof Object.create === 'function') { + // implementation from standard node.js 'util' module + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); + }; +} else { + // old school shim for old browsers + module.exports = function inherits(ctor, superCtor) { + ctor.super_ = superCtor + var TempCtor = function () {} + TempCtor.prototype = superCtor.prototype + ctor.prototype = new TempCtor() + ctor.prototype.constructor = ctor + } +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/is-buffer/index.js":[function(require,module,exports){ +/*! + * Determine if an object is a Buffer + * + * @author Feross Aboukhadijeh + * @license MIT + */ + +// The _isBuffer check is for Safari 5-7 support, because it's missing +// Object.prototype.constructor. Remove this eventually +module.exports = function (obj) { + return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer) +} + +function isBuffer (obj) { + return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj) +} + +// For Node v0.10 support. Remove this eventually. +function isSlowBuffer (obj) { + return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0)) +} + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/isarray/index.js":[function(require,module,exports){ +var toString = {}.toString; + +module.exports = Array.isArray || function (arr) { + return toString.call(arr) == '[object Array]'; +}; + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/long/dist/long.js":[function(require,module,exports){ +/* + Copyright 2013 Daniel Wirtz + Copyright 2009 The Closure Library Authors. 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. + */ + +/** + * @license long.js (c) 2013 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/long.js for details + */ +(function(global, factory) { + + /* AMD */ if (typeof define === 'function' && define["amd"]) + define([], factory); + /* CommonJS */ else if (typeof require === 'function' && typeof module === "object" && module && module["exports"]) + module["exports"] = factory(); + /* Global */ else + (global["dcodeIO"] = global["dcodeIO"] || {})["Long"] = factory(); + +})(this, function() { + "use strict"; + + /** + * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers. + * See the from* functions below for more convenient ways of constructing Longs. + * @exports Long + * @class A Long class for representing a 64 bit two's-complement integer value. + * @param {number} low The low (signed) 32 bits of the long + * @param {number} high The high (signed) 32 bits of the long + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @constructor + */ + function Long(low, high, unsigned) { + + /** + * The low 32 bits as a signed value. + * @type {number} + */ + this.low = low | 0; + + /** + * The high 32 bits as a signed value. + * @type {number} + */ + this.high = high | 0; + + /** + * Whether unsigned or not. + * @type {boolean} + */ + this.unsigned = !!unsigned; + } + + // The internal representation of a long is the two given signed, 32-bit values. + // We use 32-bit pieces because these are the size of integers on which + // Javascript performs bit-operations. For operations like addition and + // multiplication, we split each number into 16 bit pieces, which can easily be + // multiplied within Javascript's floating-point representation without overflow + // or change in sign. + // + // In the algorithms below, we frequently reduce the negative case to the + // positive case by negating the input(s) and then post-processing the result. + // Note that we must ALWAYS check specially whether those values are MIN_VALUE + // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + // a positive number, it overflows back into a negative). Not handling this + // case would often result in infinite recursion. + // + // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from* + // methods on which they depend. + + /** + * An indicator used to reliably determine if an object is a Long or not. + * @type {boolean} + * @const + * @private + */ + Long.prototype.__isLong__; + + Object.defineProperty(Long.prototype, "__isLong__", { + value: true, + enumerable: false, + configurable: false + }); + + /** + * @function + * @param {*} obj Object + * @returns {boolean} + * @inner + */ + function isLong(obj) { + return (obj && obj["__isLong__"]) === true; + } + + /** + * Tests if the specified object is a Long. + * @function + * @param {*} obj Object + * @returns {boolean} + */ + Long.isLong = isLong; + + /** + * A cache of the Long representations of small integer values. + * @type {!Object} + * @inner + */ + var INT_CACHE = {}; + + /** + * A cache of the Long representations of small unsigned integer values. + * @type {!Object} + * @inner + */ + var UINT_CACHE = {}; + + /** + * @param {number} value + * @param {boolean=} unsigned + * @returns {!Long} + * @inner + */ + function fromInt(value, unsigned) { + var obj, cachedObj, cache; + if (unsigned) { + value >>>= 0; + if (cache = (0 <= value && value < 256)) { + cachedObj = UINT_CACHE[value]; + if (cachedObj) + return cachedObj; + } + obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true); + if (cache) + UINT_CACHE[value] = obj; + return obj; + } else { + value |= 0; + if (cache = (-128 <= value && value < 128)) { + cachedObj = INT_CACHE[value]; + if (cachedObj) + return cachedObj; + } + obj = fromBits(value, value < 0 ? -1 : 0, false); + if (cache) + INT_CACHE[value] = obj; + return obj; + } + } + + /** + * Returns a Long representing the given 32 bit integer value. + * @function + * @param {number} value The 32 bit integer in question + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Long} The corresponding Long value + */ + Long.fromInt = fromInt; + + /** + * @param {number} value + * @param {boolean=} unsigned + * @returns {!Long} + * @inner + */ + function fromNumber(value, unsigned) { + if (isNaN(value) || !isFinite(value)) + return unsigned ? UZERO : ZERO; + if (unsigned) { + if (value < 0) + return UZERO; + if (value >= TWO_PWR_64_DBL) + return MAX_UNSIGNED_VALUE; + } else { + if (value <= -TWO_PWR_63_DBL) + return MIN_VALUE; + if (value + 1 >= TWO_PWR_63_DBL) + return MAX_VALUE; + } + if (value < 0) + return fromNumber(-value, unsigned).neg(); + return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned); + } + + /** + * Returns a Long representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * @function + * @param {number} value The number in question + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Long} The corresponding Long value + */ + Long.fromNumber = fromNumber; + + /** + * @param {number} lowBits + * @param {number} highBits + * @param {boolean=} unsigned + * @returns {!Long} + * @inner + */ + function fromBits(lowBits, highBits, unsigned) { + return new Long(lowBits, highBits, unsigned); + } + + /** + * Returns a Long representing the 64 bit integer that comes by concatenating the given low and high bits. Each is + * assumed to use 32 bits. + * @function + * @param {number} lowBits The low 32 bits + * @param {number} highBits The high 32 bits + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Long} The corresponding Long value + */ + Long.fromBits = fromBits; + + /** + * @function + * @param {number} base + * @param {number} exponent + * @returns {number} + * @inner + */ + var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4) + + /** + * @param {string} str + * @param {(boolean|number)=} unsigned + * @param {number=} radix + * @returns {!Long} + * @inner + */ + function fromString(str, unsigned, radix) { + if (str.length === 0) + throw Error('empty string'); + if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity") + return ZERO; + if (typeof unsigned === 'number') { + // For goog.math.long compatibility + radix = unsigned, + unsigned = false; + } else { + unsigned = !! unsigned; + } + radix = radix || 10; + if (radix < 2 || 36 < radix) + throw RangeError('radix'); + + var p; + if ((p = str.indexOf('-')) > 0) + throw Error('interior hyphen'); + else if (p === 0) { + return fromString(str.substring(1), unsigned, radix).neg(); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = fromNumber(pow_dbl(radix, 8)); + + var result = ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i), + value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = fromNumber(pow_dbl(radix, size)); + result = result.mul(power).add(fromNumber(value)); + } else { + result = result.mul(radixToPower); + result = result.add(fromNumber(value)); + } + } + result.unsigned = unsigned; + return result; + } + + /** + * Returns a Long representation of the given string, written using the specified radix. + * @function + * @param {string} str The textual representation of the Long + * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed + * @param {number=} radix The radix in which the text is written (2-36), defaults to 10 + * @returns {!Long} The corresponding Long value + */ + Long.fromString = fromString; + + /** + * @function + * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val + * @returns {!Long} + * @inner + */ + function fromValue(val) { + if (val /* is compatible */ instanceof Long) + return val; + if (typeof val === 'number') + return fromNumber(val); + if (typeof val === 'string') + return fromString(val); + // Throws for non-objects, converts non-instanceof Long: + return fromBits(val.low, val.high, val.unsigned); + } + + /** + * Converts the specified value to a Long. + * @function + * @param {!Long|number|string|!{low: number, high: number, unsigned: boolean}} val Value + * @returns {!Long} + */ + Long.fromValue = fromValue; + + // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be + // no runtime penalty for these. + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_16_DBL = 1 << 16; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_24_DBL = 1 << 24; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2; + + /** + * @type {!Long} + * @const + * @inner + */ + var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL); + + /** + * @type {!Long} + * @inner + */ + var ZERO = fromInt(0); + + /** + * Signed zero. + * @type {!Long} + */ + Long.ZERO = ZERO; + + /** + * @type {!Long} + * @inner + */ + var UZERO = fromInt(0, true); + + /** + * Unsigned zero. + * @type {!Long} + */ + Long.UZERO = UZERO; + + /** + * @type {!Long} + * @inner + */ + var ONE = fromInt(1); + + /** + * Signed one. + * @type {!Long} + */ + Long.ONE = ONE; + + /** + * @type {!Long} + * @inner + */ + var UONE = fromInt(1, true); + + /** + * Unsigned one. + * @type {!Long} + */ + Long.UONE = UONE; + + /** + * @type {!Long} + * @inner + */ + var NEG_ONE = fromInt(-1); + + /** + * Signed negative one. + * @type {!Long} + */ + Long.NEG_ONE = NEG_ONE; + + /** + * @type {!Long} + * @inner + */ + var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false); + + /** + * Maximum signed value. + * @type {!Long} + */ + Long.MAX_VALUE = MAX_VALUE; + + /** + * @type {!Long} + * @inner + */ + var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true); + + /** + * Maximum unsigned value. + * @type {!Long} + */ + Long.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE; + + /** + * @type {!Long} + * @inner + */ + var MIN_VALUE = fromBits(0, 0x80000000|0, false); + + /** + * Minimum signed value. + * @type {!Long} + */ + Long.MIN_VALUE = MIN_VALUE; + + /** + * @alias Long.prototype + * @inner + */ + var LongPrototype = Long.prototype; + + /** + * Converts the Long to a 32 bit integer, assuming it is a 32 bit integer. + * @returns {number} + */ + LongPrototype.toInt = function toInt() { + return this.unsigned ? this.low >>> 0 : this.low; + }; + + /** + * Converts the Long to a the nearest floating-point representation of this value (double, 53 bit mantissa). + * @returns {number} + */ + LongPrototype.toNumber = function toNumber() { + if (this.unsigned) + return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0); + return this.high * TWO_PWR_32_DBL + (this.low >>> 0); + }; + + /** + * Converts the Long to a string written in the specified radix. + * @param {number=} radix Radix (2-36), defaults to 10 + * @returns {string} + * @override + * @throws {RangeError} If `radix` is out of range + */ + LongPrototype.toString = function toString(radix) { + radix = radix || 10; + if (radix < 2 || 36 < radix) + throw RangeError('radix'); + if (this.isZero()) + return '0'; + if (this.isNegative()) { // Unsigned Longs are never negative + if (this.eq(MIN_VALUE)) { + // We need to change the Long value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixLong = fromNumber(radix), + div = this.div(radixLong), + rem1 = div.mul(radixLong).sub(this); + return div.toString(radix) + rem1.toInt().toString(radix); + } else + return '-' + this.neg().toString(radix); + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned), + rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower), + intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0, + digits = intval.toString(radix); + rem = remDiv; + if (rem.isZero()) + return digits + result; + else { + while (digits.length < 6) + digits = '0' + digits; + result = '' + digits + result; + } + } + }; + + /** + * Gets the high 32 bits as a signed integer. + * @returns {number} Signed high bits + */ + LongPrototype.getHighBits = function getHighBits() { + return this.high; + }; + + /** + * Gets the high 32 bits as an unsigned integer. + * @returns {number} Unsigned high bits + */ + LongPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() { + return this.high >>> 0; + }; + + /** + * Gets the low 32 bits as a signed integer. + * @returns {number} Signed low bits + */ + LongPrototype.getLowBits = function getLowBits() { + return this.low; + }; + + /** + * Gets the low 32 bits as an unsigned integer. + * @returns {number} Unsigned low bits + */ + LongPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() { + return this.low >>> 0; + }; + + /** + * Gets the number of bits needed to represent the absolute value of this Long. + * @returns {number} + */ + LongPrototype.getNumBitsAbs = function getNumBitsAbs() { + if (this.isNegative()) // Unsigned Longs are never negative + return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs(); + var val = this.high != 0 ? this.high : this.low; + for (var bit = 31; bit > 0; bit--) + if ((val & (1 << bit)) != 0) + break; + return this.high != 0 ? bit + 33 : bit + 1; + }; + + /** + * Tests if this Long's value equals zero. + * @returns {boolean} + */ + LongPrototype.isZero = function isZero() { + return this.high === 0 && this.low === 0; + }; + + /** + * Tests if this Long's value is negative. + * @returns {boolean} + */ + LongPrototype.isNegative = function isNegative() { + return !this.unsigned && this.high < 0; + }; + + /** + * Tests if this Long's value is positive. + * @returns {boolean} + */ + LongPrototype.isPositive = function isPositive() { + return this.unsigned || this.high >= 0; + }; + + /** + * Tests if this Long's value is odd. + * @returns {boolean} + */ + LongPrototype.isOdd = function isOdd() { + return (this.low & 1) === 1; + }; + + /** + * Tests if this Long's value is even. + * @returns {boolean} + */ + LongPrototype.isEven = function isEven() { + return (this.low & 1) === 0; + }; + + /** + * Tests if this Long's value equals the specified's. + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.equals = function equals(other) { + if (!isLong(other)) + other = fromValue(other); + if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) + return false; + return this.high === other.high && this.low === other.low; + }; + + /** + * Tests if this Long's value equals the specified's. This is an alias of {@link Long#equals}. + * @function + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.eq = LongPrototype.equals; + + /** + * Tests if this Long's value differs from the specified's. + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.notEquals = function notEquals(other) { + return !this.eq(/* validates */ other); + }; + + /** + * Tests if this Long's value differs from the specified's. This is an alias of {@link Long#notEquals}. + * @function + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.neq = LongPrototype.notEquals; + + /** + * Tests if this Long's value is less than the specified's. + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.lessThan = function lessThan(other) { + return this.comp(/* validates */ other) < 0; + }; + + /** + * Tests if this Long's value is less than the specified's. This is an alias of {@link Long#lessThan}. + * @function + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.lt = LongPrototype.lessThan; + + /** + * Tests if this Long's value is less than or equal the specified's. + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.lessThanOrEqual = function lessThanOrEqual(other) { + return this.comp(/* validates */ other) <= 0; + }; + + /** + * Tests if this Long's value is less than or equal the specified's. This is an alias of {@link Long#lessThanOrEqual}. + * @function + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.lte = LongPrototype.lessThanOrEqual; + + /** + * Tests if this Long's value is greater than the specified's. + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.greaterThan = function greaterThan(other) { + return this.comp(/* validates */ other) > 0; + }; + + /** + * Tests if this Long's value is greater than the specified's. This is an alias of {@link Long#greaterThan}. + * @function + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.gt = LongPrototype.greaterThan; + + /** + * Tests if this Long's value is greater than or equal the specified's. + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) { + return this.comp(/* validates */ other) >= 0; + }; + + /** + * Tests if this Long's value is greater than or equal the specified's. This is an alias of {@link Long#greaterThanOrEqual}. + * @function + * @param {!Long|number|string} other Other value + * @returns {boolean} + */ + LongPrototype.gte = LongPrototype.greaterThanOrEqual; + + /** + * Compares this Long's value with the specified's. + * @param {!Long|number|string} other Other value + * @returns {number} 0 if they are the same, 1 if the this is greater and -1 + * if the given one is greater + */ + LongPrototype.compare = function compare(other) { + if (!isLong(other)) + other = fromValue(other); + if (this.eq(other)) + return 0; + var thisNeg = this.isNegative(), + otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) + return -1; + if (!thisNeg && otherNeg) + return 1; + // At this point the sign bits are the same + if (!this.unsigned) + return this.sub(other).isNegative() ? -1 : 1; + // Both are positive if at least one is unsigned + return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1; + }; + + /** + * Compares this Long's value with the specified's. This is an alias of {@link Long#compare}. + * @function + * @param {!Long|number|string} other Other value + * @returns {number} 0 if they are the same, 1 if the this is greater and -1 + * if the given one is greater + */ + LongPrototype.comp = LongPrototype.compare; + + /** + * Negates this Long's value. + * @returns {!Long} Negated Long + */ + LongPrototype.negate = function negate() { + if (!this.unsigned && this.eq(MIN_VALUE)) + return MIN_VALUE; + return this.not().add(ONE); + }; + + /** + * Negates this Long's value. This is an alias of {@link Long#negate}. + * @function + * @returns {!Long} Negated Long + */ + LongPrototype.neg = LongPrototype.negate; + + /** + * Returns the sum of this and the specified Long. + * @param {!Long|number|string} addend Addend + * @returns {!Long} Sum + */ + LongPrototype.add = function add(addend) { + if (!isLong(addend)) + addend = fromValue(addend); + + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high >>> 16; + var a32 = this.high & 0xFFFF; + var a16 = this.low >>> 16; + var a00 = this.low & 0xFFFF; + + var b48 = addend.high >>> 16; + var b32 = addend.high & 0xFFFF; + var b16 = addend.low >>> 16; + var b00 = addend.low & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned); + }; + + /** + * Returns the difference of this and the specified Long. + * @param {!Long|number|string} subtrahend Subtrahend + * @returns {!Long} Difference + */ + LongPrototype.subtract = function subtract(subtrahend) { + if (!isLong(subtrahend)) + subtrahend = fromValue(subtrahend); + return this.add(subtrahend.neg()); + }; + + /** + * Returns the difference of this and the specified Long. This is an alias of {@link Long#subtract}. + * @function + * @param {!Long|number|string} subtrahend Subtrahend + * @returns {!Long} Difference + */ + LongPrototype.sub = LongPrototype.subtract; + + /** + * Returns the product of this and the specified Long. + * @param {!Long|number|string} multiplier Multiplier + * @returns {!Long} Product + */ + LongPrototype.multiply = function multiply(multiplier) { + if (this.isZero()) + return ZERO; + if (!isLong(multiplier)) + multiplier = fromValue(multiplier); + if (multiplier.isZero()) + return ZERO; + if (this.eq(MIN_VALUE)) + return multiplier.isOdd() ? MIN_VALUE : ZERO; + if (multiplier.eq(MIN_VALUE)) + return this.isOdd() ? MIN_VALUE : ZERO; + + if (this.isNegative()) { + if (multiplier.isNegative()) + return this.neg().mul(multiplier.neg()); + else + return this.neg().mul(multiplier).neg(); + } else if (multiplier.isNegative()) + return this.mul(multiplier.neg()).neg(); + + // If both longs are small, use float multiplication + if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24)) + return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned); + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high >>> 16; + var a32 = this.high & 0xFFFF; + var a16 = this.low >>> 16; + var a00 = this.low & 0xFFFF; + + var b48 = multiplier.high >>> 16; + var b32 = multiplier.high & 0xFFFF; + var b16 = multiplier.low >>> 16; + var b00 = multiplier.low & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned); + }; + + /** + * Returns the product of this and the specified Long. This is an alias of {@link Long#multiply}. + * @function + * @param {!Long|number|string} multiplier Multiplier + * @returns {!Long} Product + */ + LongPrototype.mul = LongPrototype.multiply; + + /** + * Returns this Long divided by the specified. The result is signed if this Long is signed or + * unsigned if this Long is unsigned. + * @param {!Long|number|string} divisor Divisor + * @returns {!Long} Quotient + */ + LongPrototype.divide = function divide(divisor) { + if (!isLong(divisor)) + divisor = fromValue(divisor); + if (divisor.isZero()) + throw Error('division by zero'); + if (this.isZero()) + return this.unsigned ? UZERO : ZERO; + var approx, rem, res; + if (!this.unsigned) { + // This section is only relevant for signed longs and is derived from the + // closure library as a whole. + if (this.eq(MIN_VALUE)) { + if (divisor.eq(ONE) || divisor.eq(NEG_ONE)) + return MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + else if (divisor.eq(MIN_VALUE)) + return ONE; + else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shr(1); + approx = halfThis.div(divisor).shl(1); + if (approx.eq(ZERO)) { + return divisor.isNegative() ? ONE : NEG_ONE; + } else { + rem = this.sub(divisor.mul(approx)); + res = approx.add(rem.div(divisor)); + return res; + } + } + } else if (divisor.eq(MIN_VALUE)) + return this.unsigned ? UZERO : ZERO; + if (this.isNegative()) { + if (divisor.isNegative()) + return this.neg().div(divisor.neg()); + return this.neg().div(divisor).neg(); + } else if (divisor.isNegative()) + return this.div(divisor.neg()).neg(); + res = ZERO; + } else { + // The algorithm below has not been made for unsigned longs. It's therefore + // required to take special care of the MSB prior to running it. + if (!divisor.unsigned) + divisor = divisor.toUnsigned(); + if (divisor.gt(this)) + return UZERO; + if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true + return UONE; + res = UZERO; + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + rem = this; + while (rem.gte(divisor)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2), + delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48), + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + approxRes = fromNumber(approx), + approxRem = approxRes.mul(divisor); + while (approxRem.isNegative() || approxRem.gt(rem)) { + approx -= delta; + approxRes = fromNumber(approx, this.unsigned); + approxRem = approxRes.mul(divisor); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) + approxRes = ONE; + + res = res.add(approxRes); + rem = rem.sub(approxRem); + } + return res; + }; + + /** + * Returns this Long divided by the specified. This is an alias of {@link Long#divide}. + * @function + * @param {!Long|number|string} divisor Divisor + * @returns {!Long} Quotient + */ + LongPrototype.div = LongPrototype.divide; + + /** + * Returns this Long modulo the specified. + * @param {!Long|number|string} divisor Divisor + * @returns {!Long} Remainder + */ + LongPrototype.modulo = function modulo(divisor) { + if (!isLong(divisor)) + divisor = fromValue(divisor); + return this.sub(this.div(divisor).mul(divisor)); + }; + + /** + * Returns this Long modulo the specified. This is an alias of {@link Long#modulo}. + * @function + * @param {!Long|number|string} divisor Divisor + * @returns {!Long} Remainder + */ + LongPrototype.mod = LongPrototype.modulo; + + /** + * Returns the bitwise NOT of this Long. + * @returns {!Long} + */ + LongPrototype.not = function not() { + return fromBits(~this.low, ~this.high, this.unsigned); + }; + + /** + * Returns the bitwise AND of this Long and the specified. + * @param {!Long|number|string} other Other Long + * @returns {!Long} + */ + LongPrototype.and = function and(other) { + if (!isLong(other)) + other = fromValue(other); + return fromBits(this.low & other.low, this.high & other.high, this.unsigned); + }; + + /** + * Returns the bitwise OR of this Long and the specified. + * @param {!Long|number|string} other Other Long + * @returns {!Long} + */ + LongPrototype.or = function or(other) { + if (!isLong(other)) + other = fromValue(other); + return fromBits(this.low | other.low, this.high | other.high, this.unsigned); + }; + + /** + * Returns the bitwise XOR of this Long and the given one. + * @param {!Long|number|string} other Other Long + * @returns {!Long} + */ + LongPrototype.xor = function xor(other) { + if (!isLong(other)) + other = fromValue(other); + return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned); + }; + + /** + * Returns this Long with bits shifted to the left by the given amount. + * @param {number|!Long} numBits Number of bits + * @returns {!Long} Shifted Long + */ + LongPrototype.shiftLeft = function shiftLeft(numBits) { + if (isLong(numBits)) + numBits = numBits.toInt(); + if ((numBits &= 63) === 0) + return this; + else if (numBits < 32) + return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned); + else + return fromBits(0, this.low << (numBits - 32), this.unsigned); + }; + + /** + * Returns this Long with bits shifted to the left by the given amount. This is an alias of {@link Long#shiftLeft}. + * @function + * @param {number|!Long} numBits Number of bits + * @returns {!Long} Shifted Long + */ + LongPrototype.shl = LongPrototype.shiftLeft; + + /** + * Returns this Long with bits arithmetically shifted to the right by the given amount. + * @param {number|!Long} numBits Number of bits + * @returns {!Long} Shifted Long + */ + LongPrototype.shiftRight = function shiftRight(numBits) { + if (isLong(numBits)) + numBits = numBits.toInt(); + if ((numBits &= 63) === 0) + return this; + else if (numBits < 32) + return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned); + else + return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned); + }; + + /** + * Returns this Long with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Long#shiftRight}. + * @function + * @param {number|!Long} numBits Number of bits + * @returns {!Long} Shifted Long + */ + LongPrototype.shr = LongPrototype.shiftRight; + + /** + * Returns this Long with bits logically shifted to the right by the given amount. + * @param {number|!Long} numBits Number of bits + * @returns {!Long} Shifted Long + */ + LongPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) { + if (isLong(numBits)) + numBits = numBits.toInt(); + numBits &= 63; + if (numBits === 0) + return this; + else { + var high = this.high; + if (numBits < 32) { + var low = this.low; + return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned); + } else if (numBits === 32) + return fromBits(high, 0, this.unsigned); + else + return fromBits(high >>> (numBits - 32), 0, this.unsigned); + } + }; + + /** + * Returns this Long with bits logically shifted to the right by the given amount. This is an alias of {@link Long#shiftRightUnsigned}. + * @function + * @param {number|!Long} numBits Number of bits + * @returns {!Long} Shifted Long + */ + LongPrototype.shru = LongPrototype.shiftRightUnsigned; + + /** + * Converts this Long to signed. + * @returns {!Long} Signed long + */ + LongPrototype.toSigned = function toSigned() { + if (!this.unsigned) + return this; + return fromBits(this.low, this.high, false); + }; + + /** + * Converts this Long to unsigned. + * @returns {!Long} Unsigned long + */ + LongPrototype.toUnsigned = function toUnsigned() { + if (this.unsigned) + return this; + return fromBits(this.low, this.high, true); + }; + + /** + * Converts this Long to its byte representation. + * @param {boolean=} le Whether little or big endian, defaults to big endian + * @returns {!Array.} Byte representation + */ + LongPrototype.toBytes = function(le) { + return le ? this.toBytesLE() : this.toBytesBE(); + } + + /** + * Converts this Long to its little endian byte representation. + * @returns {!Array.} Little endian byte representation + */ + LongPrototype.toBytesLE = function() { + var hi = this.high, + lo = this.low; + return [ + lo & 0xff, + (lo >>> 8) & 0xff, + (lo >>> 16) & 0xff, + (lo >>> 24) & 0xff, + hi & 0xff, + (hi >>> 8) & 0xff, + (hi >>> 16) & 0xff, + (hi >>> 24) & 0xff + ]; + } + + /** + * Converts this Long to its big endian byte representation. + * @returns {!Array.} Big endian byte representation + */ + LongPrototype.toBytesBE = function() { + var hi = this.high, + lo = this.low; + return [ + (hi >>> 24) & 0xff, + (hi >>> 16) & 0xff, + (hi >>> 8) & 0xff, + hi & 0xff, + (lo >>> 24) & 0xff, + (lo >>> 16) & 0xff, + (lo >>> 8) & 0xff, + lo & 0xff + ]; + } + + return Long; +}); + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/md5.js/index.js":[function(require,module,exports){ +(function (Buffer){ +'use strict' +var inherits = require('inherits') +var HashBase = require('hash-base') + +var ARRAY16 = new Array(16) + +function MD5 () { + HashBase.call(this, 64) + + // state + this._a = 0x67452301 + this._b = 0xefcdab89 + this._c = 0x98badcfe + this._d = 0x10325476 +} + +inherits(MD5, HashBase) + +MD5.prototype._update = function () { + var M = ARRAY16 + for (var i = 0; i < 16; ++i) M[i] = this._block.readInt32LE(i * 4) + + var a = this._a + var b = this._b + var c = this._c + var d = this._d + + a = fnF(a, b, c, d, M[0], 0xd76aa478, 7) + d = fnF(d, a, b, c, M[1], 0xe8c7b756, 12) + c = fnF(c, d, a, b, M[2], 0x242070db, 17) + b = fnF(b, c, d, a, M[3], 0xc1bdceee, 22) + a = fnF(a, b, c, d, M[4], 0xf57c0faf, 7) + d = fnF(d, a, b, c, M[5], 0x4787c62a, 12) + c = fnF(c, d, a, b, M[6], 0xa8304613, 17) + b = fnF(b, c, d, a, M[7], 0xfd469501, 22) + a = fnF(a, b, c, d, M[8], 0x698098d8, 7) + d = fnF(d, a, b, c, M[9], 0x8b44f7af, 12) + c = fnF(c, d, a, b, M[10], 0xffff5bb1, 17) + b = fnF(b, c, d, a, M[11], 0x895cd7be, 22) + a = fnF(a, b, c, d, M[12], 0x6b901122, 7) + d = fnF(d, a, b, c, M[13], 0xfd987193, 12) + c = fnF(c, d, a, b, M[14], 0xa679438e, 17) + b = fnF(b, c, d, a, M[15], 0x49b40821, 22) + + a = fnG(a, b, c, d, M[1], 0xf61e2562, 5) + d = fnG(d, a, b, c, M[6], 0xc040b340, 9) + c = fnG(c, d, a, b, M[11], 0x265e5a51, 14) + b = fnG(b, c, d, a, M[0], 0xe9b6c7aa, 20) + a = fnG(a, b, c, d, M[5], 0xd62f105d, 5) + d = fnG(d, a, b, c, M[10], 0x02441453, 9) + c = fnG(c, d, a, b, M[15], 0xd8a1e681, 14) + b = fnG(b, c, d, a, M[4], 0xe7d3fbc8, 20) + a = fnG(a, b, c, d, M[9], 0x21e1cde6, 5) + d = fnG(d, a, b, c, M[14], 0xc33707d6, 9) + c = fnG(c, d, a, b, M[3], 0xf4d50d87, 14) + b = fnG(b, c, d, a, M[8], 0x455a14ed, 20) + a = fnG(a, b, c, d, M[13], 0xa9e3e905, 5) + d = fnG(d, a, b, c, M[2], 0xfcefa3f8, 9) + c = fnG(c, d, a, b, M[7], 0x676f02d9, 14) + b = fnG(b, c, d, a, M[12], 0x8d2a4c8a, 20) + + a = fnH(a, b, c, d, M[5], 0xfffa3942, 4) + d = fnH(d, a, b, c, M[8], 0x8771f681, 11) + c = fnH(c, d, a, b, M[11], 0x6d9d6122, 16) + b = fnH(b, c, d, a, M[14], 0xfde5380c, 23) + a = fnH(a, b, c, d, M[1], 0xa4beea44, 4) + d = fnH(d, a, b, c, M[4], 0x4bdecfa9, 11) + c = fnH(c, d, a, b, M[7], 0xf6bb4b60, 16) + b = fnH(b, c, d, a, M[10], 0xbebfbc70, 23) + a = fnH(a, b, c, d, M[13], 0x289b7ec6, 4) + d = fnH(d, a, b, c, M[0], 0xeaa127fa, 11) + c = fnH(c, d, a, b, M[3], 0xd4ef3085, 16) + b = fnH(b, c, d, a, M[6], 0x04881d05, 23) + a = fnH(a, b, c, d, M[9], 0xd9d4d039, 4) + d = fnH(d, a, b, c, M[12], 0xe6db99e5, 11) + c = fnH(c, d, a, b, M[15], 0x1fa27cf8, 16) + b = fnH(b, c, d, a, M[2], 0xc4ac5665, 23) + + a = fnI(a, b, c, d, M[0], 0xf4292244, 6) + d = fnI(d, a, b, c, M[7], 0x432aff97, 10) + c = fnI(c, d, a, b, M[14], 0xab9423a7, 15) + b = fnI(b, c, d, a, M[5], 0xfc93a039, 21) + a = fnI(a, b, c, d, M[12], 0x655b59c3, 6) + d = fnI(d, a, b, c, M[3], 0x8f0ccc92, 10) + c = fnI(c, d, a, b, M[10], 0xffeff47d, 15) + b = fnI(b, c, d, a, M[1], 0x85845dd1, 21) + a = fnI(a, b, c, d, M[8], 0x6fa87e4f, 6) + d = fnI(d, a, b, c, M[15], 0xfe2ce6e0, 10) + c = fnI(c, d, a, b, M[6], 0xa3014314, 15) + b = fnI(b, c, d, a, M[13], 0x4e0811a1, 21) + a = fnI(a, b, c, d, M[4], 0xf7537e82, 6) + d = fnI(d, a, b, c, M[11], 0xbd3af235, 10) + c = fnI(c, d, a, b, M[2], 0x2ad7d2bb, 15) + b = fnI(b, c, d, a, M[9], 0xeb86d391, 21) + + this._a = (this._a + a) | 0 + this._b = (this._b + b) | 0 + this._c = (this._c + c) | 0 + this._d = (this._d + d) | 0 +} + +MD5.prototype._digest = function () { + // create padding and handle blocks + this._block[this._blockOffset++] = 0x80 + if (this._blockOffset > 56) { + this._block.fill(0, this._blockOffset, 64) + this._update() + this._blockOffset = 0 + } + + this._block.fill(0, this._blockOffset, 56) + this._block.writeUInt32LE(this._length[0], 56) + this._block.writeUInt32LE(this._length[1], 60) + this._update() + + // produce result + var buffer = new Buffer(16) + buffer.writeInt32LE(this._a, 0) + buffer.writeInt32LE(this._b, 4) + buffer.writeInt32LE(this._c, 8) + buffer.writeInt32LE(this._d, 12) + return buffer +} + +function rotl (x, n) { + return (x << n) | (x >>> (32 - n)) +} + +function fnF (a, b, c, d, m, k, s) { + return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + b) | 0 +} + +function fnG (a, b, c, d, m, k, s) { + return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + b) | 0 +} + +function fnH (a, b, c, d, m, k, s) { + return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + b) | 0 +} + +function fnI (a, b, c, d, m, k, s) { + return (rotl((a + ((c ^ (b | (~d)))) + m + k) | 0, s) + b) | 0 +} + +module.exports = MD5 + +}).call(this,require("buffer").Buffer) + +},{"buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","hash-base":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/hash-base/index.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/index.js":[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; +exports.Manager = exports.ChainConfig = exports.Apis = undefined; + +var _ApiInstances = require('./src/ApiInstances'); + +var _ApiInstances2 = _interopRequireDefault(_ApiInstances); + +var _ConnectionManager = require('./src/ConnectionManager'); + +var _ConnectionManager2 = _interopRequireDefault(_ConnectionManager); + +var _ChainConfig = require('./src/ChainConfig'); + +var _ChainConfig2 = _interopRequireDefault(_ChainConfig); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +exports.Apis = _ApiInstances2.default; +exports.ChainConfig = _ChainConfig2.default; +exports.Manager = _ConnectionManager2.default; +},{"./src/ApiInstances":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ApiInstances.js","./src/ChainConfig":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ChainConfig.js","./src/ConnectionManager":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ConnectionManager.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ApiInstances.js":[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _ChainWebSocket = require('./ChainWebSocket'); + +var _ChainWebSocket2 = _interopRequireDefault(_ChainWebSocket); + +var _GrapheneApi = require('./GrapheneApi'); + +var _GrapheneApi2 = _interopRequireDefault(_GrapheneApi); + +var _ChainConfig = require('./ChainConfig'); + +var _ChainConfig2 = _interopRequireDefault(_ChainConfig); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var inst = void 0; + +var ApisInstance = function () { + function ApisInstance() { + _classCallCheck(this, ApisInstance); + } + + /** @arg {string} connection .. */ + ApisInstance.prototype.connect = function connect(cs, connectTimeout) { + var _this = this; + + var rpc_user = ''; + var rpc_password = ''; + + if (typeof window !== 'undefined' && window.location && window.location.protocol === 'https:' && cs.indexOf('wss://') < 0) { + throw new Error('Secure domains require wss connection'); + } + + this.ws_rpc = new _ChainWebSocket2.default(cs, this.statusCb, connectTimeout); + + this.init_promise = this.ws_rpc.login(rpc_user, rpc_password).then(function () { + console.log('Connected to API node:', cs); + _this._db = new _GrapheneApi2.default(_this.ws_rpc, 'database'); + _this._net = new _GrapheneApi2.default(_this.ws_rpc, 'network_broadcast'); + _this._hist = new _GrapheneApi2.default(_this.ws_rpc, 'history'); + _this._crypto = new _GrapheneApi2.default(_this.ws_rpc, 'crypto'); + _this._bookie = new _GrapheneApi2.default(_this.ws_rpc, 'bookie'); + var db_promise = _this._db.init().then(function () { + return _this._db.exec('get_chain_id', []).then(function (_chain_id) { + _this.chain_id = _chain_id; + return _ChainConfig2.default.setChainId(_chain_id); + }); + }); + + _this.ws_rpc.on_reconnect = function () { + _this.ws_rpc.login('', '').then(function () { + _this._db.init().then(function () { + if (_this.statusCb) { + _this.statusCb(_ChainWebSocket2.default.status.RECONNECTED); + } + }); + _this._net.init(); + _this._hist.init(); + _this._crypto.init(); + _this._bookie.init(); + }); + }; + + return Promise.all([db_promise, _this._net.init(), _this._hist.init(), + // Temporary squash crypto API error until the API is upgraded everywhere + _this._crypto.init().catch(function (e) { + return console.error('ApiInstance\tCrypto API Error', e); + }), _this._bookie.init()]); + }); + }; + + ApisInstance.prototype.close = function close() { + if (this.ws_rpc) { + this.ws_rpc.close(); + } + + this.ws_rpc = null; + }; + + ApisInstance.prototype.db_api = function db_api() { + return this._db; + }; + + ApisInstance.prototype.network_api = function network_api() { + return this._net; + }; + + ApisInstance.prototype.history_api = function history_api() { + return this._hist; + }; + + ApisInstance.prototype.crypto_api = function crypto_api() { + return this._crypto; + }; + + ApisInstance.prototype.bookie_api = function bookie_api() { + return this._bookie; + }; + + ApisInstance.prototype.setRpcConnectionStatusCallback = function setRpcConnectionStatusCallback(callback) { + this.statusCb = callback; + }; + + return ApisInstance; +}(); + +/** + Configure: configure as follows `Apis.instance("ws://localhost:8090").init_promise`. This + returns a promise, once resolved the connection is ready. + + Import: import { Apis } from "@graphene/chain" + + Short-hand: Apis.db("method", "parm1", 2, 3, ...). Returns a promise with results. + + Additional usage: Apis.instance().db_api().exec("method", ["method", "parm1", 2, 3, ...]). + Returns a promise with results. +*/ + +exports.default = { + setRpcConnectionStatusCallback: function setRpcConnectionStatusCallback(callback) { + this.statusCb = callback; + + if (inst) { + inst.setRpcConnectionStatusCallback(callback); + } + }, + + /** + @arg {string} cs is only provided in the first call + @return {Apis} singleton .. Check Apis.instance().init_promise to + know when the connection is established + */ + reset: function reset() { + var cs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'ws://localhost:8090'; + var connect = arguments[1]; + var connectTimeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 4000; + + if (inst) { + inst.close(); + inst = null; + } + + inst = new ApisInstance(); + inst.setRpcConnectionStatusCallback(this.statusCb); + + if (inst && connect) { + inst.connect(cs, connectTimeout); + } + + return inst; + }, + instance: function instance() { + var cs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'ws://localhost:8090'; + var connect = arguments[1]; + var connectTimeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 4000; + + if (!inst) { + inst = new ApisInstance(); + inst.setRpcConnectionStatusCallback(this.statusCb); + } + + if (inst && connect) { + inst.connect(cs, connectTimeout); + } + + return inst; + }, + chainId: function chainId() { + return this.instance().chain_id; + }, + close: function close() { + if (inst) { + inst.close(); + inst = null; + } + } + // db: (method, ...args) => Apis.instance().db_api().exec(method, toStrings(args)), + // network: (method, ...args) => Apis.instance().network_api().exec(method, toStrings(args)), + // history: (method, ...args) => Apis.instance().history_api().exec(method, toStrings(args)), + // crypto: (method, ...args) => Apis.instance().crypto_api().exec(method, toStrings(args)) + +}; +},{"./ChainConfig":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ChainConfig.js","./ChainWebSocket":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ChainWebSocket.js","./GrapheneApi":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/GrapheneApi.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ChainConfig.js":[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var defaults = { + core_asset: 'PPY', + address_prefix: 'PPY', + expire_in_secs: 15, + expire_in_secs_proposal: 24 * 60 * 60, + review_in_secs_committee: 24 * 60 * 60 +}; + +var networks = { + networks: { + Peerplays: { + core_asset: 'PPY', + address_prefix: 'PPY', + chain_id: '6b6b5f0ce7a36d323768e534f3edb41c6d6332a541a95725b98e28d140850134' + }, + PeerplaysTestnet: { + core_asset: 'PPYTEST', + address_prefix: 'PPYTEST', + chain_id: 'be6b79295e728406cbb7494bcb626e62ad278fa4018699cf8f75739f4c1a81fd' + } + } +}; + +var ChainConfig = function () { + function ChainConfig() { + _classCallCheck(this, ChainConfig); + + this.reset(); + } + + ChainConfig.prototype.reset = function reset() { + Object.assign(this, defaults); + }; + + ChainConfig.prototype.setChainId = function setChainId(chainID) { + var ref = Object.keys(networks); + + for (var i = 0, len = ref.length; i < len; i++) { + var network_name = ref[i]; + var network = networks[network_name]; + + if (network.chain_id === chainID) { + this.network_name = network_name; + + if (network.address_prefix) { + this.address_prefix = network.address_prefix; + } + + return { + network_name: network_name, + network: network + }; + } + } + + if (!this.network_name) { + console.log('Unknown chain id (this may be a testnet)', chainID); + } + }; + + ChainConfig.prototype.setPrefix = function setPrefix() { + var prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'PPY'; + + this.address_prefix = prefix; + }; + + return ChainConfig; +}(); + +exports.default = new ChainConfig(); +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ChainWebSocket.js":[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var SOCKET_DEBUG = false; +var WebSocketClient = null; + +if (typeof WebSocket !== 'undefined') { + WebSocketClient = WebSocket; +} else { + WebSocketClient = require('ws'); // eslint-disable-line global-require +} + +var SUBSCRIBE_OPERATIONS = ['set_subscribe_callback', 'subscribe_to_market', 'broadcast_transaction_with_callback', 'set_pending_transaction_callback']; + +var UNSUBSCRIBE_OPERATIONS = ['unsubscribe_from_market', 'unsubscribe_from_accounts']; + +var HEALTH_CHECK_INTERVAL = 10000; + +var ChainWebSocket = function () { + /** + *Creates an instance of ChainWebSocket. + * @param {string} serverAddress The address of the websocket to connect to. + * @param {function} statusCb Called when status events occur. + * @param {number} [connectTimeout=10000] The time for a connection attempt to complete. + * @memberof ChainWebSocket + */ + function ChainWebSocket(serverAddress, statusCb) { + var connectTimeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 10000; + + _classCallCheck(this, ChainWebSocket); + + this.statusCb = statusCb; + this.serverAddress = serverAddress; + this.timeoutInterval = connectTimeout; + + // The currenct connection state of the websocket. + this.connected = false; + this.reconnectTimeout = null; + + // Callback to execute when the websocket is reconnected. + this.on_reconnect = null; + + // An incrementing ID for each request so that we can pair it with the + // response from the websocket. + this.cbId = 0; + + // Objects to store key/value pairs for callbacks, subscription callbacks + // and unsubscribe callbacks. + this.cbs = {}; + this.subs = {}; + this.unsub = {}; + + // Current connection promises' rejection + this.currentResolve = null; + this.currentReject = null; + + // Health check for the connection to the BlockChain. + this.healthCheck = null; + + // Copy the constants to this instance. + this.status = ChainWebSocket.status; + + // Bind the functions to the instance. + this.onConnectionOpen = this.onConnectionOpen.bind(this); + this.onConnectionClose = this.onConnectionClose.bind(this); + this.onConnectionTerminate = this.onConnectionTerminate.bind(this); + this.onConnectionError = this.onConnectionError.bind(this); + this.onConnectionTimeout = this.onConnectionTimeout.bind(this); + this.createConnection = this.createConnection.bind(this); + this.createConnectionPromise = this.createConnectionPromise.bind(this); + this.listener = this.listener.bind(this); + + // Create the initial connection the blockchain. + this.createConnection(); + } + + /** + * Create the connection to the Blockchain. + * + * @returns + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.createConnection = function createConnection() { + this.debug('!!! ChainWebSocket create connection'); + + // Clear any possible reconnect timers. + this.reconnectTimeout = null; + + // Create the promise for this connection + if (!this.connect_promise) { + this.connect_promise = new Promise(this.createConnectionPromise); + } + + // Attempt to create the websocket + try { + this.ws = new WebSocketClient(this.serverAddress); + } catch (error) { + // Set a timeout to try and reconnect here. + return this.resetConnection(); + } + + this.addEventListeners(); + + // Handle timeouts to the websocket's initial connection. + this.connectionTimeout = setTimeout(this.onConnectionTimeout, this.timeoutInterval); + }; + + /** + * Reset the connection to the BlockChain. + * + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.resetConnection = function resetConnection() { + // Close the Websocket if its still 'half-open' + this.close(); + + // Make sure we only ever have one timeout running to reconnect. + if (!this.reconnectTimeout) { + this.debug('!!! ChainWebSocket reset connection', this.timeoutInterval); + this.reconnectTimeout = setTimeout(this.createConnection, this.timeoutInterval); + } + + // Reject the current promise if there is one. + if (this.currentReject) { + this.currentReject(new Error('Connection attempt failed: ' + this.serverAddress)); + } + }; + + /** + * Add event listeners to the WebSocket. + * + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.addEventListeners = function addEventListeners() { + this.debug('!!! ChainWebSocket add event listeners'); + this.ws.addEventListener('open', this.onConnectionOpen); + this.ws.addEventListener('close', this.onConnectionClose); + this.ws.addEventListener('error', this.onConnectionError); + this.ws.addEventListener('message', this.listener); + }; + + /** + * Remove the event listers from the WebSocket. Its important to remove the event listerers + * for garbaage collection. Because we are creating a new WebSocket on each connection attempt + * any listeners that are still attached could prevent the old sockets from + * being garbage collected. + * + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.removeEventListeners = function removeEventListeners() { + this.debug('!!! ChainWebSocket remove event listeners'); + this.ws.removeEventListener('open', this.onConnectionOpen); + this.ws.removeEventListener('close', this.onConnectionClose); + this.ws.removeEventListener('error', this.onConnectionError); + this.ws.removeEventListener('message', this.listener); + }; + + /** + * A function that is passed to a new promise that stores the resolve and reject callbacks + * in the state. + * + * @param {function} resolve A callback to be executed when the promise is resolved. + * @param {function} reject A callback to be executed when the promise is rejected. + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.createConnectionPromise = function createConnectionPromise(resolve, reject) { + this.debug('!!! ChainWebSocket createPromise'); + this.currentResolve = resolve; + this.currentReject = reject; + }; + + /** + * Called when a new Websocket connection is opened. + * + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.onConnectionOpen = function onConnectionOpen() { + this.debug('!!! ChainWebSocket Connected '); + + this.connected = true; + + clearTimeout(this.connectionTimeout); + this.connectionTimeout = null; + + // This will trigger the login process as well as some additional setup in ApiInstances + if (this.on_reconnect) { + this.on_reconnect(); + } + + if (this.currentResolve) { + this.currentResolve(); + } + + if (this.statusCb) { + this.statusCb(ChainWebSocket.status.OPEN); + } + }; + + /** + * called when the connection attempt times out. + * + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.onConnectionTimeout = function onConnectionTimeout() { + this.debug('!!! ChainWebSocket timeout'); + this.onConnectionClose(new Error('Connection timed out.')); + }; + + /** + * Called when the Websocket is not responding to the health checks. + * + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.onConnectionTerminate = function onConnectionTerminate() { + this.debug('!!! ChainWebSocket terminate'); + this.onConnectionClose(new Error('Connection was terminated.')); + }; + + /** + * Called when the connection to the Blockchain is closed. + * + * @param {*} error + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.onConnectionClose = function onConnectionClose(error) { + this.debug('!!! ChainWebSocket Close ', error); + + this.resetConnection(); + + if (this.statusCb) { + this.statusCb(ChainWebSocket.status.CLOSED); + } + }; + + /** + * Called when the Websocket encounters an error. + * + * @param {*} error + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.onConnectionError = function onConnectionError(error) { + this.debug('!!! ChainWebSocket On Connection Error ', error); + + this.resetConnection(); + + if (this.statusCb) { + this.statusCb(ChainWebSocket.status.ERROR); + } + }; + + /** + * Entry point to make RPC calls on the BlockChain. + * + * @param {array} params An array of params to be passed to the rpc call. [method, ...params] + * @returns A new promise for this specific call. + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.call = function call(params) { + var _this = this; + + if (!this.connected) { + this.debug('!!! ChainWebSocket Call not connected. '); + return Promise.reject(new Error('Disconnected from the BlockChain.')); + } + + this.debug('!!! ChainWebSocket Call connected. ', params); + + var request = { + method: params[1], + params: params, + id: this.cbId + 1 + }; + + this.cbId = request.id; + + if (SUBSCRIBE_OPERATIONS.includes(request.method)) { + // Store callback in subs map + this.subs[request.id] = { + callback: request.params[2][0] + }; + + // Replace callback with the callback id + request.params[2][0] = request.id; + } + + if (UNSUBSCRIBE_OPERATIONS.includes(request.method)) { + if (typeof request.params[2][0] !== 'function') { + throw new Error('First parameter of unsub must be the original callback'); + } + + var unSubCb = request.params[2].splice(0, 1)[0]; + + // Find the corresponding subscription + for (var id in this.subs) { + // eslint-disable-line + if (this.subs[id].callback === unSubCb) { + this.unsub[request.id] = id; + break; + } + } + } + + if (!this.healthCheck) { + this.healthCheck = setTimeout(this.onConnectionTerminate.bind(this), HEALTH_CHECK_INTERVAL); + } + + return new Promise(function (resolve, reject) { + _this.cbs[request.id] = { + time: new Date(), + resolve: resolve, + reject: reject + }; + + // Set all requests to be 'call' methods. + request.method = 'call'; + + try { + _this.ws.send(JSON.stringify(request)); + } catch (error) { + _this.debug('Caught a nasty error : ', error); + } + }); + }; + + /** + * Called when messages are received on the Websocket. + * + * @param {*} response The message received. + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.listener = function listener(response) { + var responseJSON = null; + + try { + responseJSON = JSON.parse(response.data); + } catch (error) { + responseJSON.error = 'Error parsing response: ' + error.stack; + this.debug('Error parsing response: ', response); + } + + // Clear the health check timeout, we've just received a healthy response from the server. + if (this.healthCheck) { + clearTimeout(this.healthCheck); + this.healthCheck = null; + } + + var sub = false; + var callback = null; + + if (responseJSON.method === 'notice') { + sub = true; + responseJSON.id = responseJSON.params[0]; + } + + if (!sub) { + callback = this.cbs[responseJSON.id]; + } else { + callback = this.subs[responseJSON.id].callback; + } + + if (callback && !sub) { + if (responseJSON.error) { + this.debug('----> responseJSON : ', responseJSON); + callback.reject(responseJSON.error); + } else { + callback.resolve(responseJSON.result); + } + + delete this.cbs[responseJSON.id]; + + if (this.unsub[responseJSON.id]) { + delete this.subs[this.unsub[responseJSON.id]]; + delete this.unsub[responseJSON.id]; + } + } else if (callback && sub) { + callback(responseJSON.params[1]); + } else { + this.debug('Warning: unknown websocket responseJSON: ', responseJSON); + } + }; + + /** + * Login to the Blockchain. + * + * @param {string} user Username + * @param {string} password Password + * @returns A promise that is fulfilled after login. + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.login = function login(user, password) { + var _this2 = this; + + this.debug('!!! ChainWebSocket login.', user, password); + return this.connect_promise.then(function () { + return _this2.call([1, 'login', [user, password]]); + }); + }; + + /** + * Close the connection to the Blockchain. + * + * @memberof ChainWebSocket + */ + + + ChainWebSocket.prototype.close = function close() { + if (this.ws) { + this.removeEventListeners(); + + // Try and fire close on the connection. + this.ws.close(); + + // Clear our references so that it can be garbage collected. + this.ws = null; + } + + // Clear our timeouts for connection timeout and health check. + clearTimeout(this.connectionTimeout); + this.connectionTimeout = null; + + clearTimeout(this.healthCheck); + this.healthCheck = null; + + clearTimeout(this.reconnectTimeout); + this.reconnectTimeout = null; + + // Toggle the connected flag. + this.connected = false; + }; + + ChainWebSocket.prototype.debug = function debug() { + if (SOCKET_DEBUG) { + for (var _len = arguments.length, params = Array(_len), _key = 0; _key < _len; _key++) { + params[_key] = arguments[_key]; + } + + console.log.apply(null, params); + } + }; + + return ChainWebSocket; +}(); + +// Constants for STATE + + +ChainWebSocket.status = { + RECONNECTED: 'reconnected', + OPEN: 'open', + CLOSED: 'closed', + ERROR: 'error' +}; + +exports.default = ChainWebSocket; +},{"ws":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browser-resolve/empty.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ConnectionManager.js":[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +var _ApiInstances = require('./ApiInstances'); + +var _ApiInstances2 = _interopRequireDefault(_ApiInstances); + +var _ChainWebSocket = require('./ChainWebSocket'); + +var _ChainWebSocket2 = _interopRequireDefault(_ChainWebSocket); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Manager = function () { + function Manager(_ref) { + var url = _ref.url, + urls = _ref.urls; + + _classCallCheck(this, Manager); + + this.url = url; + this.urls = urls.filter(function (a) { + return a !== url; + }); + } + + Manager.prototype.logFailure = function logFailure(url) { + console.error('Unable to connect to', url + ', skipping to next full node API server'); + }; + + Manager.prototype.connect = function connect() { + var _connect = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + + var url = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.url; + + return new Promise(function (resolve, reject) { + _ApiInstances2.default.instance(url, _connect).init_promise.then(resolve).catch(function (error) { + _ApiInstances2.default.instance().close(); + reject(error); + }); + }); + }; + + Manager.prototype.connectWithFallback = function connectWithFallback() { + var connect = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true; + var url = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.url; + var index = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0; + + var _this = this; + + var resolve = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + var reject = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; + + if (reject && index > this.urls.length - 1) { + return reject(new Error('Tried ' + (index + 1) + ' connections, none of which worked: ' + JSON.stringify(this.urls.concat(this.url)))); + } + + var fallback = function fallback(resolve, reject) { + _this.logFailure(url); + return _this.connectWithFallback(connect, _this.urls[index], index + 1, resolve, reject); + }; + + if (resolve && reject) { + return this.connect(connect, url).then(resolve).catch(function () { + fallback(resolve, reject); + }); + } + + return new Promise(function (resolve, reject) { + _this.connect(connect).then(resolve).catch(function () { + fallback(resolve, reject); + }); + }); + }; + + Manager.prototype.checkConnections = function checkConnections() { + var rpc_user = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ''; + var rpc_password = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ''; + + var _this2 = this; + + var resolve = arguments[2]; + var reject = arguments[3]; + + var connectionStartTimes = {}; + + var checkFunction = function checkFunction(resolve, reject) { + var fullList = _this2.urls.concat(_this2.url); + var connectionPromises = []; + + fullList.forEach(function (url) { + var conn = new _ChainWebSocket2.default(url, function () {}); + connectionStartTimes[url] = new Date().getTime(); + connectionPromises.push(function () { + return conn.login(rpc_user, rpc_password).then(function () { + var _ref2; + + conn.close(); + return _ref2 = {}, _ref2[url] = new Date().getTime() - connectionStartTimes[url], _ref2; + }).catch(function () { + if (url === _this2.url) { + _this2.url = _this2.urls[0]; + } else { + _this2.urls = _this2.urls.filter(function (a) { + return a !== url; + }); + } + + conn.close(); + return null; + }); + }); + }); + + Promise.all(connectionPromises.map(function (a) { + return a(); + })).then(function (res) { + resolve(res.filter(function (a) { + return !!a; + }).reduce(function (f, a) { + var key = Object.keys(a)[0]; + f[key] = a[key]; + return f; + }, {})); + }).catch(function () { + return _this2.checkConnections(rpc_user, rpc_password, resolve, reject); + }); + }; + + if (resolve && reject) { + checkFunction(resolve, reject); + } else { + return new Promise(checkFunction); + } + }; + + return Manager; +}(); + +exports.default = Manager; +},{"./ApiInstances":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ApiInstances.js","./ChainWebSocket":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/ChainWebSocket.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/peerplaysjs-ws/dist/src/GrapheneApi.js":[function(require,module,exports){ +'use strict'; + +exports.__esModule = true; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var GrapheneApi = function () { + function GrapheneApi(ws_rpc, api_name) { + _classCallCheck(this, GrapheneApi); + + this.ws_rpc = ws_rpc; + this.api_name = api_name; + } + + GrapheneApi.prototype.init = function init() { + var _this = this; + + return this.ws_rpc.call([1, this.api_name, []]).then(function (response) { + _this.api_id = response; + return _this; + }); + }; + + GrapheneApi.prototype.exec = function exec(method, params) { + return this.ws_rpc.call([this.api_id, method, params]).catch(function (error) { + console.log('!!! GrapheneApi error: ', method, params, error, JSON.stringify(error)); + throw error; + }); + }; + + return GrapheneApi; +}(); + +exports.default = GrapheneApi; +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process-nextick-args/index.js":[function(require,module,exports){ +(function (process){ +'use strict'; + +if (!process.version || + process.version.indexOf('v0.') === 0 || + process.version.indexOf('v1.') === 0 && process.version.indexOf('v1.8.') !== 0) { + module.exports = { nextTick: nextTick }; +} else { + module.exports = process +} + +function nextTick(fn, arg1, arg2, arg3) { + if (typeof fn !== 'function') { + throw new TypeError('"callback" argument must be a function'); + } + var len = arguments.length; + var args, i; + switch (len) { + case 0: + case 1: + return process.nextTick(fn); + case 2: + return process.nextTick(function afterTickOne() { + fn.call(null, arg1); + }); + case 3: + return process.nextTick(function afterTickTwo() { + fn.call(null, arg1, arg2); + }); + case 4: + return process.nextTick(function afterTickThree() { + fn.call(null, arg1, arg2, arg3); + }); + default: + args = new Array(len - 1); + i = 0; + while (i < args.length) { + args[i++] = arguments[i]; + } + return process.nextTick(function afterTick() { + fn.apply(null, args); + }); + } +} + + +}).call(this,require('_process')) + +},{"_process":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js":[function(require,module,exports){ +// shim for using process in browser +var process = module.exports = {}; + +// cached from whatever global is present so that test runners that stub it +// don't break things. But we need to wrap it in a try catch in case it is +// wrapped in strict mode code which doesn't define any globals. It's inside a +// function because try/catches deoptimize in certain engines. + +var cachedSetTimeout; +var cachedClearTimeout; + +function defaultSetTimout() { + throw new Error('setTimeout has not been defined'); +} +function defaultClearTimeout () { + throw new Error('clearTimeout has not been defined'); +} +(function () { + try { + if (typeof setTimeout === 'function') { + cachedSetTimeout = setTimeout; + } else { + cachedSetTimeout = defaultSetTimout; + } + } catch (e) { + cachedSetTimeout = defaultSetTimout; + } + try { + if (typeof clearTimeout === 'function') { + cachedClearTimeout = clearTimeout; + } else { + cachedClearTimeout = defaultClearTimeout; + } + } catch (e) { + cachedClearTimeout = defaultClearTimeout; + } +} ()) +function runTimeout(fun) { + if (cachedSetTimeout === setTimeout) { + //normal enviroments in sane situations + return setTimeout(fun, 0); + } + // if setTimeout wasn't available but was latter defined + if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) { + cachedSetTimeout = setTimeout; + return setTimeout(fun, 0); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedSetTimeout(fun, 0); + } catch(e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedSetTimeout.call(null, fun, 0); + } catch(e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error + return cachedSetTimeout.call(this, fun, 0); + } + } + + +} +function runClearTimeout(marker) { + if (cachedClearTimeout === clearTimeout) { + //normal enviroments in sane situations + return clearTimeout(marker); + } + // if clearTimeout wasn't available but was latter defined + if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) { + cachedClearTimeout = clearTimeout; + return clearTimeout(marker); + } + try { + // when when somebody has screwed with setTimeout but no I.E. maddness + return cachedClearTimeout(marker); + } catch (e){ + try { + // When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally + return cachedClearTimeout.call(null, marker); + } catch (e){ + // same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error. + // Some versions of I.E. have different rules for clearTimeout vs setTimeout + return cachedClearTimeout.call(this, marker); + } + } + + + +} +var queue = []; +var draining = false; +var currentQueue; +var queueIndex = -1; + +function cleanUpNextTick() { + if (!draining || !currentQueue) { + return; + } + draining = false; + if (currentQueue.length) { + queue = currentQueue.concat(queue); + } else { + queueIndex = -1; + } + if (queue.length) { + drainQueue(); + } +} + +function drainQueue() { + if (draining) { + return; + } + var timeout = runTimeout(cleanUpNextTick); + draining = true; + + var len = queue.length; + while(len) { + currentQueue = queue; + queue = []; + while (++queueIndex < len) { + if (currentQueue) { + currentQueue[queueIndex].run(); + } + } + queueIndex = -1; + len = queue.length; + } + currentQueue = null; + draining = false; + runClearTimeout(timeout); +} + +process.nextTick = function (fun) { + var args = new Array(arguments.length - 1); + if (arguments.length > 1) { + for (var i = 1; i < arguments.length; i++) { + args[i - 1] = arguments[i]; + } + } + queue.push(new Item(fun, args)); + if (queue.length === 1 && !draining) { + runTimeout(drainQueue); + } +}; + +// v8 likes predictible objects +function Item(fun, array) { + this.fun = fun; + this.array = array; +} +Item.prototype.run = function () { + this.fun.apply(null, this.array); +}; +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; +process.version = ''; // empty string to avoid regexp issues +process.versions = {}; + +function noop() {} + +process.on = noop; +process.addListener = noop; +process.once = noop; +process.off = noop; +process.removeListener = noop; +process.removeAllListeners = noop; +process.emit = noop; +process.prependListener = noop; +process.prependOnceListener = noop; + +process.listeners = function (name) { return [] } + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +}; + +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; +process.umask = function() { return 0; }; + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/duplex-browser.js":[function(require,module,exports){ +module.exports = require('./lib/_stream_duplex.js'); + +},{"./lib/_stream_duplex.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_duplex.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_duplex.js":[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a duplex stream is just a stream that is both readable and writable. +// Since JS doesn't have multiple prototypal inheritance, this class +// prototypally inherits from Readable, and then parasitically from +// Writable. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +/**/ +var objectKeys = Object.keys || function (obj) { + var keys = []; + for (var key in obj) { + keys.push(key); + }return keys; +}; +/**/ + +module.exports = Duplex; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +var Readable = require('./_stream_readable'); +var Writable = require('./_stream_writable'); + +util.inherits(Duplex, Readable); + +{ + // avoid scope creep, the keys array can then be collected + var keys = objectKeys(Writable.prototype); + for (var v = 0; v < keys.length; v++) { + var method = keys[v]; + if (!Duplex.prototype[method]) Duplex.prototype[method] = Writable.prototype[method]; + } +} + +function Duplex(options) { + if (!(this instanceof Duplex)) return new Duplex(options); + + Readable.call(this, options); + Writable.call(this, options); + + if (options && options.readable === false) this.readable = false; + + if (options && options.writable === false) this.writable = false; + + this.allowHalfOpen = true; + if (options && options.allowHalfOpen === false) this.allowHalfOpen = false; + + this.once('end', onend); +} + +Object.defineProperty(Duplex.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// the no-half-open enforcer +function onend() { + // if we allow half-open state, or if the writable side ended, + // then we're ok. + if (this.allowHalfOpen || this._writableState.ended) return; + + // no more data can be written. + // But allow more writes to happen in this tick. + pna.nextTick(onEndNT, this); +} + +function onEndNT(self) { + self.end(); +} + +Object.defineProperty(Duplex.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined || this._writableState === undefined) { + return false; + } + return this._readableState.destroyed && this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (this._readableState === undefined || this._writableState === undefined) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + this._writableState.destroyed = value; + } +}); + +Duplex.prototype._destroy = function (err, cb) { + this.push(null); + this.end(); + + pna.nextTick(cb, err); +}; +},{"./_stream_readable":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_readable.js","./_stream_writable":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_writable.js","core-util-is":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/core-util-is/lib/util.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","process-nextick-args":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process-nextick-args/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_passthrough.js":[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a passthrough stream. +// basically just the most minimal sort of Transform stream. +// Every written chunk gets output as-is. + +'use strict'; + +module.exports = PassThrough; + +var Transform = require('./_stream_transform'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(PassThrough, Transform); + +function PassThrough(options) { + if (!(this instanceof PassThrough)) return new PassThrough(options); + + Transform.call(this, options); +} + +PassThrough.prototype._transform = function (chunk, encoding, cb) { + cb(null, chunk); +}; +},{"./_stream_transform":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_transform.js","core-util-is":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/core-util-is/lib/util.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_readable.js":[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Readable; + +/**/ +var isArray = require('isarray'); +/**/ + +/**/ +var Duplex; +/**/ + +Readable.ReadableState = ReadableState; + +/**/ +var EE = require('events').EventEmitter; + +var EElistenerCount = function (emitter, type) { + return emitter.listeners(type).length; +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var debugUtil = require('util'); +var debug = void 0; +if (debugUtil && debugUtil.debuglog) { + debug = debugUtil.debuglog('stream'); +} else { + debug = function () {}; +} +/**/ + +var BufferList = require('./internal/streams/BufferList'); +var destroyImpl = require('./internal/streams/destroy'); +var StringDecoder; + +util.inherits(Readable, Stream); + +var kProxyEvents = ['error', 'close', 'destroy', 'pause', 'resume']; + +function prependListener(emitter, event, fn) { + // Sadly this is not cacheable as some libraries bundle their own + // event emitter implementation with them. + if (typeof emitter.prependListener === 'function') return emitter.prependListener(event, fn); + + // This is a hack to make sure that our error handler is attached before any + // userland ones. NEVER DO THIS. This is here only because this code needs + // to continue to work with older versions of Node.js that do not include + // the prependListener() method. The goal is to eventually remove this hack. + if (!emitter._events || !emitter._events[event]) emitter.on(event, fn);else if (isArray(emitter._events[event])) emitter._events[event].unshift(fn);else emitter._events[event] = [fn, emitter._events[event]]; +} + +function ReadableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag. Used to make read(n) ignore n and to + // make all the buffer merging and length checks go away + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.readableObjectMode; + + // the point at which it stops calling _read() to fill the buffer + // Note: 0 is a valid value, means "don't call _read preemptively ever" + var hwm = options.highWaterMark; + var readableHwm = options.readableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (readableHwm || readableHwm === 0)) this.highWaterMark = readableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // A linked list is used to store data chunks instead of an array because the + // linked list can remove elements from the beginning faster than + // array.shift() + this.buffer = new BufferList(); + this.length = 0; + this.pipes = null; + this.pipesCount = 0; + this.flowing = null; + this.ended = false; + this.endEmitted = false; + this.reading = false; + + // a flag to be able to tell if the event 'readable'/'data' is emitted + // immediately, or on a later tick. We set this to true at first, because + // any actions that shouldn't happen until "later" should generally also + // not happen before the first read call. + this.sync = true; + + // whenever we return null, then we set a flag to say + // that we're awaiting a 'readable' event emission. + this.needReadable = false; + this.emittedReadable = false; + this.readableListening = false; + this.resumeScheduled = false; + + // has it been destroyed + this.destroyed = false; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // the number of writers that are awaiting a drain event in .pipe()s + this.awaitDrain = 0; + + // if true, a maybeReadMore has been scheduled + this.readingMore = false; + + this.decoder = null; + this.encoding = null; + if (options.encoding) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this.decoder = new StringDecoder(options.encoding); + this.encoding = options.encoding; + } +} + +function Readable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + if (!(this instanceof Readable)) return new Readable(options); + + this._readableState = new ReadableState(options, this); + + // legacy + this.readable = true; + + if (options) { + if (typeof options.read === 'function') this._read = options.read; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + } + + Stream.call(this); +} + +Object.defineProperty(Readable.prototype, 'destroyed', { + get: function () { + if (this._readableState === undefined) { + return false; + } + return this._readableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._readableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._readableState.destroyed = value; + } +}); + +Readable.prototype.destroy = destroyImpl.destroy; +Readable.prototype._undestroy = destroyImpl.undestroy; +Readable.prototype._destroy = function (err, cb) { + this.push(null); + cb(err); +}; + +// Manually shove something into the read() buffer. +// This returns true if the highWaterMark has not been hit yet, +// similar to how Writable.write() returns true if you should +// write() some more. +Readable.prototype.push = function (chunk, encoding) { + var state = this._readableState; + var skipChunkCheck; + + if (!state.objectMode) { + if (typeof chunk === 'string') { + encoding = encoding || state.defaultEncoding; + if (encoding !== state.encoding) { + chunk = Buffer.from(chunk, encoding); + encoding = ''; + } + skipChunkCheck = true; + } + } else { + skipChunkCheck = true; + } + + return readableAddChunk(this, chunk, encoding, false, skipChunkCheck); +}; + +// Unshift should *always* be something directly out of read() +Readable.prototype.unshift = function (chunk) { + return readableAddChunk(this, chunk, null, true, false); +}; + +function readableAddChunk(stream, chunk, encoding, addToFront, skipChunkCheck) { + var state = stream._readableState; + if (chunk === null) { + state.reading = false; + onEofChunk(stream, state); + } else { + var er; + if (!skipChunkCheck) er = chunkInvalid(state, chunk); + if (er) { + stream.emit('error', er); + } else if (state.objectMode || chunk && chunk.length > 0) { + if (typeof chunk !== 'string' && !state.objectMode && Object.getPrototypeOf(chunk) !== Buffer.prototype) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (addToFront) { + if (state.endEmitted) stream.emit('error', new Error('stream.unshift() after end event'));else addChunk(stream, state, chunk, true); + } else if (state.ended) { + stream.emit('error', new Error('stream.push() after EOF')); + } else { + state.reading = false; + if (state.decoder && !encoding) { + chunk = state.decoder.write(chunk); + if (state.objectMode || chunk.length !== 0) addChunk(stream, state, chunk, false);else maybeReadMore(stream, state); + } else { + addChunk(stream, state, chunk, false); + } + } + } else if (!addToFront) { + state.reading = false; + } + } + + return needMoreData(state); +} + +function addChunk(stream, state, chunk, addToFront) { + if (state.flowing && state.length === 0 && !state.sync) { + stream.emit('data', chunk); + stream.read(0); + } else { + // update the buffer info. + state.length += state.objectMode ? 1 : chunk.length; + if (addToFront) state.buffer.unshift(chunk);else state.buffer.push(chunk); + + if (state.needReadable) emitReadable(stream); + } + maybeReadMore(stream, state); +} + +function chunkInvalid(state, chunk) { + var er; + if (!_isUint8Array(chunk) && typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + return er; +} + +// if it's past the high water mark, we can push in some more. +// Also, if we have no data yet, we can stand some +// more bytes. This is to work around cases where hwm=0, +// such as the repl. Also, if the push() triggered a +// readable event, and the user called read(largeNumber) such that +// needReadable was set, then we ought to push more, so that another +// 'readable' event will be triggered. +function needMoreData(state) { + return !state.ended && (state.needReadable || state.length < state.highWaterMark || state.length === 0); +} + +Readable.prototype.isPaused = function () { + return this._readableState.flowing === false; +}; + +// backwards compatibility. +Readable.prototype.setEncoding = function (enc) { + if (!StringDecoder) StringDecoder = require('string_decoder/').StringDecoder; + this._readableState.decoder = new StringDecoder(enc); + this._readableState.encoding = enc; + return this; +}; + +// Don't raise the hwm > 8MB +var MAX_HWM = 0x800000; +function computeNewHighWaterMark(n) { + if (n >= MAX_HWM) { + n = MAX_HWM; + } else { + // Get the next highest power of 2 to prevent increasing hwm excessively in + // tiny amounts + n--; + n |= n >>> 1; + n |= n >>> 2; + n |= n >>> 4; + n |= n >>> 8; + n |= n >>> 16; + n++; + } + return n; +} + +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function howMuchToRead(n, state) { + if (n <= 0 || state.length === 0 && state.ended) return 0; + if (state.objectMode) return 1; + if (n !== n) { + // Only flow one buffer at a time + if (state.flowing && state.length) return state.buffer.head.data.length;else return state.length; + } + // If we're asking for more than the current hwm, then raise the hwm. + if (n > state.highWaterMark) state.highWaterMark = computeNewHighWaterMark(n); + if (n <= state.length) return n; + // Don't have enough + if (!state.ended) { + state.needReadable = true; + return 0; + } + return state.length; +} + +// you can override either this method, or the async _read(n) below. +Readable.prototype.read = function (n) { + debug('read', n); + n = parseInt(n, 10); + var state = this._readableState; + var nOrig = n; + + if (n !== 0) state.emittedReadable = false; + + // if we're doing read(0) to trigger a readable event, but we + // already have a bunch of data in the buffer, then just trigger + // the 'readable' event and move on. + if (n === 0 && state.needReadable && (state.length >= state.highWaterMark || state.ended)) { + debug('read: emitReadable', state.length, state.ended); + if (state.length === 0 && state.ended) endReadable(this);else emitReadable(this); + return null; + } + + n = howMuchToRead(n, state); + + // if we've ended, and we're now clear, then finish it up. + if (n === 0 && state.ended) { + if (state.length === 0) endReadable(this); + return null; + } + + // All the actual chunk generation logic needs to be + // *below* the call to _read. The reason is that in certain + // synthetic stream cases, such as passthrough streams, _read + // may be a completely synchronous operation which may change + // the state of the read buffer, providing enough data when + // before there was *not* enough. + // + // So, the steps are: + // 1. Figure out what the state of things will be after we do + // a read from the buffer. + // + // 2. If that resulting state will trigger a _read, then call _read. + // Note that this may be asynchronous, or synchronous. Yes, it is + // deeply ugly to write APIs this way, but that still doesn't mean + // that the Readable class should behave improperly, as streams are + // designed to be sync/async agnostic. + // Take note if the _read call is sync or async (ie, if the read call + // has returned yet), so that we know whether or not it's safe to emit + // 'readable' etc. + // + // 3. Actually pull the requested chunks out of the buffer and return. + + // if we need a readable event, then we need to do some reading. + var doRead = state.needReadable; + debug('need readable', doRead); + + // if we currently have less than the highWaterMark, then also read some + if (state.length === 0 || state.length - n < state.highWaterMark) { + doRead = true; + debug('length less than watermark', doRead); + } + + // however, if we've ended, then there's no point, and if we're already + // reading, then it's unnecessary. + if (state.ended || state.reading) { + doRead = false; + debug('reading or ended', doRead); + } else if (doRead) { + debug('do read'); + state.reading = true; + state.sync = true; + // if the length is currently zero, then we *need* a readable event. + if (state.length === 0) state.needReadable = true; + // call internal read method + this._read(state.highWaterMark); + state.sync = false; + // If _read pushed data synchronously, then `reading` will be false, + // and we need to re-evaluate how much data we can return to the user. + if (!state.reading) n = howMuchToRead(nOrig, state); + } + + var ret; + if (n > 0) ret = fromList(n, state);else ret = null; + + if (ret === null) { + state.needReadable = true; + n = 0; + } else { + state.length -= n; + } + + if (state.length === 0) { + // If we have nothing in the buffer, then we want to know + // as soon as we *do* get something into the buffer. + if (!state.ended) state.needReadable = true; + + // If we tried to read() past the EOF, then emit end on the next tick. + if (nOrig !== n && state.ended) endReadable(this); + } + + if (ret !== null) this.emit('data', ret); + + return ret; +}; + +function onEofChunk(stream, state) { + if (state.ended) return; + if (state.decoder) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) { + state.buffer.push(chunk); + state.length += state.objectMode ? 1 : chunk.length; + } + } + state.ended = true; + + // emit 'readable' now to make sure it gets picked up. + emitReadable(stream); +} + +// Don't emit readable right away in sync mode, because this can trigger +// another read() call => stack overflow. This way, it might trigger +// a nextTick recursion warning, but that's not so bad. +function emitReadable(stream) { + var state = stream._readableState; + state.needReadable = false; + if (!state.emittedReadable) { + debug('emitReadable', state.flowing); + state.emittedReadable = true; + if (state.sync) pna.nextTick(emitReadable_, stream);else emitReadable_(stream); + } +} + +function emitReadable_(stream) { + debug('emit readable'); + stream.emit('readable'); + flow(stream); +} + +// at this point, the user has presumably seen the 'readable' event, +// and called read() to consume some data. that may have triggered +// in turn another _read(n) call, in which case reading = true if +// it's in progress. +// However, if we're not ended, or reading, and the length < hwm, +// then go ahead and try to read some more preemptively. +function maybeReadMore(stream, state) { + if (!state.readingMore) { + state.readingMore = true; + pna.nextTick(maybeReadMore_, stream, state); + } +} + +function maybeReadMore_(stream, state) { + var len = state.length; + while (!state.reading && !state.flowing && !state.ended && state.length < state.highWaterMark) { + debug('maybeReadMore read 0'); + stream.read(0); + if (len === state.length) + // didn't get any data, stop spinning. + break;else len = state.length; + } + state.readingMore = false; +} + +// abstract method. to be overridden in specific implementation classes. +// call cb(er, data) where data is <= n in length. +// for virtual (non-string, non-buffer) streams, "length" is somewhat +// arbitrary, and perhaps not very meaningful. +Readable.prototype._read = function (n) { + this.emit('error', new Error('_read() is not implemented')); +}; + +Readable.prototype.pipe = function (dest, pipeOpts) { + var src = this; + var state = this._readableState; + + switch (state.pipesCount) { + case 0: + state.pipes = dest; + break; + case 1: + state.pipes = [state.pipes, dest]; + break; + default: + state.pipes.push(dest); + break; + } + state.pipesCount += 1; + debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts); + + var doEnd = (!pipeOpts || pipeOpts.end !== false) && dest !== process.stdout && dest !== process.stderr; + + var endFn = doEnd ? onend : unpipe; + if (state.endEmitted) pna.nextTick(endFn);else src.once('end', endFn); + + dest.on('unpipe', onunpipe); + function onunpipe(readable, unpipeInfo) { + debug('onunpipe'); + if (readable === src) { + if (unpipeInfo && unpipeInfo.hasUnpiped === false) { + unpipeInfo.hasUnpiped = true; + cleanup(); + } + } + } + + function onend() { + debug('onend'); + dest.end(); + } + + // when the dest drains, it reduces the awaitDrain counter + // on the source. This would be more elegant with a .once() + // handler in flow(), but adding and removing repeatedly is + // too slow. + var ondrain = pipeOnDrain(src); + dest.on('drain', ondrain); + + var cleanedUp = false; + function cleanup() { + debug('cleanup'); + // cleanup event handlers once the pipe is broken + dest.removeListener('close', onclose); + dest.removeListener('finish', onfinish); + dest.removeListener('drain', ondrain); + dest.removeListener('error', onerror); + dest.removeListener('unpipe', onunpipe); + src.removeListener('end', onend); + src.removeListener('end', unpipe); + src.removeListener('data', ondata); + + cleanedUp = true; + + // if the reader is waiting for a drain event from this + // specific writer, then it would cause it to never start + // flowing again. + // So, if this is awaiting a drain, then we just call it now. + // If we don't know, then assume that we are waiting for one. + if (state.awaitDrain && (!dest._writableState || dest._writableState.needDrain)) ondrain(); + } + + // If the user pushes more data while we're writing to dest then we'll end up + // in ondata again. However, we only want to increase awaitDrain once because + // dest will only emit one 'drain' event for the multiple writes. + // => Introduce a guard on increasing awaitDrain. + var increasedAwaitDrain = false; + src.on('data', ondata); + function ondata(chunk) { + debug('ondata'); + increasedAwaitDrain = false; + var ret = dest.write(chunk); + if (false === ret && !increasedAwaitDrain) { + // If the user unpiped during `dest.write()`, it is possible + // to get stuck in a permanently paused state if that write + // also returned false. + // => Check whether `dest` is still a piping destination. + if ((state.pipesCount === 1 && state.pipes === dest || state.pipesCount > 1 && indexOf(state.pipes, dest) !== -1) && !cleanedUp) { + debug('false write response, pause', src._readableState.awaitDrain); + src._readableState.awaitDrain++; + increasedAwaitDrain = true; + } + src.pause(); + } + } + + // if the dest has an error, then stop piping into it. + // however, don't suppress the throwing behavior for this. + function onerror(er) { + debug('onerror', er); + unpipe(); + dest.removeListener('error', onerror); + if (EElistenerCount(dest, 'error') === 0) dest.emit('error', er); + } + + // Make sure our error handler is attached before userland ones. + prependListener(dest, 'error', onerror); + + // Both close and finish should trigger unpipe, but only once. + function onclose() { + dest.removeListener('finish', onfinish); + unpipe(); + } + dest.once('close', onclose); + function onfinish() { + debug('onfinish'); + dest.removeListener('close', onclose); + unpipe(); + } + dest.once('finish', onfinish); + + function unpipe() { + debug('unpipe'); + src.unpipe(dest); + } + + // tell the dest that it's being piped to + dest.emit('pipe', src); + + // start the flow if it hasn't been started already. + if (!state.flowing) { + debug('pipe resume'); + src.resume(); + } + + return dest; +}; + +function pipeOnDrain(src) { + return function () { + var state = src._readableState; + debug('pipeOnDrain', state.awaitDrain); + if (state.awaitDrain) state.awaitDrain--; + if (state.awaitDrain === 0 && EElistenerCount(src, 'data')) { + state.flowing = true; + flow(src); + } + }; +} + +Readable.prototype.unpipe = function (dest) { + var state = this._readableState; + var unpipeInfo = { hasUnpiped: false }; + + // if we're not piping anywhere, then do nothing. + if (state.pipesCount === 0) return this; + + // just one destination. most common case. + if (state.pipesCount === 1) { + // passed in one, but it's not the right one. + if (dest && dest !== state.pipes) return this; + + if (!dest) dest = state.pipes; + + // got a match. + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + if (dest) dest.emit('unpipe', this, unpipeInfo); + return this; + } + + // slow case. multiple pipe destinations. + + if (!dest) { + // remove all. + var dests = state.pipes; + var len = state.pipesCount; + state.pipes = null; + state.pipesCount = 0; + state.flowing = false; + + for (var i = 0; i < len; i++) { + dests[i].emit('unpipe', this, unpipeInfo); + }return this; + } + + // try to find the right one. + var index = indexOf(state.pipes, dest); + if (index === -1) return this; + + state.pipes.splice(index, 1); + state.pipesCount -= 1; + if (state.pipesCount === 1) state.pipes = state.pipes[0]; + + dest.emit('unpipe', this, unpipeInfo); + + return this; +}; + +// set up data events if they are asked for +// Ensure readable listeners eventually get something +Readable.prototype.on = function (ev, fn) { + var res = Stream.prototype.on.call(this, ev, fn); + + if (ev === 'data') { + // Start flowing on next tick if stream isn't explicitly paused + if (this._readableState.flowing !== false) this.resume(); + } else if (ev === 'readable') { + var state = this._readableState; + if (!state.endEmitted && !state.readableListening) { + state.readableListening = state.needReadable = true; + state.emittedReadable = false; + if (!state.reading) { + pna.nextTick(nReadingNextTick, this); + } else if (state.length) { + emitReadable(this); + } + } + } + + return res; +}; +Readable.prototype.addListener = Readable.prototype.on; + +function nReadingNextTick(self) { + debug('readable nexttick read 0'); + self.read(0); +} + +// pause() and resume() are remnants of the legacy readable stream API +// If the user uses them, then switch into old mode. +Readable.prototype.resume = function () { + var state = this._readableState; + if (!state.flowing) { + debug('resume'); + state.flowing = true; + resume(this, state); + } + return this; +}; + +function resume(stream, state) { + if (!state.resumeScheduled) { + state.resumeScheduled = true; + pna.nextTick(resume_, stream, state); + } +} + +function resume_(stream, state) { + if (!state.reading) { + debug('resume read 0'); + stream.read(0); + } + + state.resumeScheduled = false; + state.awaitDrain = 0; + stream.emit('resume'); + flow(stream); + if (state.flowing && !state.reading) stream.read(0); +} + +Readable.prototype.pause = function () { + debug('call pause flowing=%j', this._readableState.flowing); + if (false !== this._readableState.flowing) { + debug('pause'); + this._readableState.flowing = false; + this.emit('pause'); + } + return this; +}; + +function flow(stream) { + var state = stream._readableState; + debug('flow', state.flowing); + while (state.flowing && stream.read() !== null) {} +} + +// wrap an old-style stream as the async data source. +// This is *not* part of the readable stream interface. +// It is an ugly unfortunate mess of history. +Readable.prototype.wrap = function (stream) { + var _this = this; + + var state = this._readableState; + var paused = false; + + stream.on('end', function () { + debug('wrapped end'); + if (state.decoder && !state.ended) { + var chunk = state.decoder.end(); + if (chunk && chunk.length) _this.push(chunk); + } + + _this.push(null); + }); + + stream.on('data', function (chunk) { + debug('wrapped data'); + if (state.decoder) chunk = state.decoder.write(chunk); + + // don't skip over falsy values in objectMode + if (state.objectMode && (chunk === null || chunk === undefined)) return;else if (!state.objectMode && (!chunk || !chunk.length)) return; + + var ret = _this.push(chunk); + if (!ret) { + paused = true; + stream.pause(); + } + }); + + // proxy all the other methods. + // important when wrapping filters and duplexes. + for (var i in stream) { + if (this[i] === undefined && typeof stream[i] === 'function') { + this[i] = function (method) { + return function () { + return stream[method].apply(stream, arguments); + }; + }(i); + } + } + + // proxy certain important events. + for (var n = 0; n < kProxyEvents.length; n++) { + stream.on(kProxyEvents[n], this.emit.bind(this, kProxyEvents[n])); + } + + // when we try to consume some more bytes, simply unpause the + // underlying stream. + this._read = function (n) { + debug('wrapped _read', n); + if (paused) { + paused = false; + stream.resume(); + } + }; + + return this; +}; + +Object.defineProperty(Readable.prototype, 'readableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._readableState.highWaterMark; + } +}); + +// exposed for testing purposes only. +Readable._fromList = fromList; + +// Pluck off n bytes from an array of buffers. +// Length is the combined lengths of all the buffers in the list. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromList(n, state) { + // nothing buffered + if (state.length === 0) return null; + + var ret; + if (state.objectMode) ret = state.buffer.shift();else if (!n || n >= state.length) { + // read it all, truncate the list + if (state.decoder) ret = state.buffer.join('');else if (state.buffer.length === 1) ret = state.buffer.head.data;else ret = state.buffer.concat(state.length); + state.buffer.clear(); + } else { + // read part of list + ret = fromListPartial(n, state.buffer, state.decoder); + } + + return ret; +} + +// Extracts only enough buffered data to satisfy the amount requested. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function fromListPartial(n, list, hasStrings) { + var ret; + if (n < list.head.data.length) { + // slice is the same for buffers and strings + ret = list.head.data.slice(0, n); + list.head.data = list.head.data.slice(n); + } else if (n === list.head.data.length) { + // first chunk is a perfect match + ret = list.shift(); + } else { + // result spans more than one buffer + ret = hasStrings ? copyFromBufferString(n, list) : copyFromBuffer(n, list); + } + return ret; +} + +// Copies a specified amount of characters from the list of buffered data +// chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBufferString(n, list) { + var p = list.head; + var c = 1; + var ret = p.data; + n -= ret.length; + while (p = p.next) { + var str = p.data; + var nb = n > str.length ? str.length : n; + if (nb === str.length) ret += str;else ret += str.slice(0, n); + n -= nb; + if (n === 0) { + if (nb === str.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = str.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +// Copies a specified amount of bytes from the list of buffered data chunks. +// This function is designed to be inlinable, so please take care when making +// changes to the function body. +function copyFromBuffer(n, list) { + var ret = Buffer.allocUnsafe(n); + var p = list.head; + var c = 1; + p.data.copy(ret); + n -= p.data.length; + while (p = p.next) { + var buf = p.data; + var nb = n > buf.length ? buf.length : n; + buf.copy(ret, ret.length - n, 0, nb); + n -= nb; + if (n === 0) { + if (nb === buf.length) { + ++c; + if (p.next) list.head = p.next;else list.head = list.tail = null; + } else { + list.head = p; + p.data = buf.slice(nb); + } + break; + } + ++c; + } + list.length -= c; + return ret; +} + +function endReadable(stream) { + var state = stream._readableState; + + // If we get here before consuming all the bytes, then that is a + // bug in node. Should never happen. + if (state.length > 0) throw new Error('"endReadable()" called on non-empty stream'); + + if (!state.endEmitted) { + state.ended = true; + pna.nextTick(endReadableNT, state, stream); + } +} + +function endReadableNT(state, stream) { + // Check that we didn't get one last unshift. + if (!state.endEmitted && state.length === 0) { + state.endEmitted = true; + stream.readable = false; + stream.emit('end'); + } +} + +function indexOf(xs, x) { + for (var i = 0, l = xs.length; i < l; i++) { + if (xs[i] === x) return i; + } + return -1; +} +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./_stream_duplex":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_duplex.js","./internal/streams/BufferList":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/BufferList.js","./internal/streams/destroy":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/destroy.js","./internal/streams/stream":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/stream-browser.js","_process":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js","core-util-is":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/core-util-is/lib/util.js","events":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/events/events.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","isarray":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/isarray/index.js","process-nextick-args":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process-nextick-args/index.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js","string_decoder/":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/string_decoder/lib/string_decoder.js","util":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browser-resolve/empty.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_transform.js":[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// a transform stream is a readable/writable stream where you do +// something with the data. Sometimes it's called a "filter", +// but that's not a great name for it, since that implies a thing where +// some bits pass through, and others are simply ignored. (That would +// be a valid example of a transform, of course.) +// +// While the output is causally related to the input, it's not a +// necessarily symmetric or synchronous transformation. For example, +// a zlib stream might take multiple plain-text writes(), and then +// emit a single compressed chunk some time in the future. +// +// Here's how this works: +// +// The Transform stream has all the aspects of the readable and writable +// stream classes. When you write(chunk), that calls _write(chunk,cb) +// internally, and returns false if there's a lot of pending writes +// buffered up. When you call read(), that calls _read(n) until +// there's enough pending readable data buffered up. +// +// In a transform stream, the written data is placed in a buffer. When +// _read(n) is called, it transforms the queued up data, calling the +// buffered _write cb's as it consumes chunks. If consuming a single +// written chunk would result in multiple output chunks, then the first +// outputted bit calls the readcb, and subsequent chunks just go into +// the read buffer, and will cause it to emit 'readable' if necessary. +// +// This way, back-pressure is actually determined by the reading side, +// since _read has to be called to start processing a new chunk. However, +// a pathological inflate type of transform can cause excessive buffering +// here. For example, imagine a stream where every byte of input is +// interpreted as an integer from 0-255, and then results in that many +// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in +// 1kb of data being output. In this case, you could write a very small +// amount of input, and end up with a very large amount of output. In +// such a pathological inflating mechanism, there'd be no way to tell +// the system to stop doing the transform. A single 4MB write could +// cause the system to run out of memory. +// +// However, even in such a pathological case, only a single written chunk +// would be consumed, and then the rest would wait (un-transformed) until +// the results of the previous transformed chunk were consumed. + +'use strict'; + +module.exports = Transform; + +var Duplex = require('./_stream_duplex'); + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +util.inherits(Transform, Duplex); + +function afterTransform(er, data) { + var ts = this._transformState; + ts.transforming = false; + + var cb = ts.writecb; + + if (!cb) { + return this.emit('error', new Error('write callback called multiple times')); + } + + ts.writechunk = null; + ts.writecb = null; + + if (data != null) // single equals check for both `null` and `undefined` + this.push(data); + + cb(er); + + var rs = this._readableState; + rs.reading = false; + if (rs.needReadable || rs.length < rs.highWaterMark) { + this._read(rs.highWaterMark); + } +} + +function Transform(options) { + if (!(this instanceof Transform)) return new Transform(options); + + Duplex.call(this, options); + + this._transformState = { + afterTransform: afterTransform.bind(this), + needTransform: false, + transforming: false, + writecb: null, + writechunk: null, + writeencoding: null + }; + + // start out asking for a readable event once data is transformed. + this._readableState.needReadable = true; + + // we have implemented the _read method, and done the other things + // that Readable wants before the first _read call, so unset the + // sync guard flag. + this._readableState.sync = false; + + if (options) { + if (typeof options.transform === 'function') this._transform = options.transform; + + if (typeof options.flush === 'function') this._flush = options.flush; + } + + // When the writable side finishes, then flush out anything remaining. + this.on('prefinish', prefinish); +} + +function prefinish() { + var _this = this; + + if (typeof this._flush === 'function') { + this._flush(function (er, data) { + done(_this, er, data); + }); + } else { + done(this, null, null); + } +} + +Transform.prototype.push = function (chunk, encoding) { + this._transformState.needTransform = false; + return Duplex.prototype.push.call(this, chunk, encoding); +}; + +// This is the part where you do stuff! +// override this function in implementation classes. +// 'chunk' is an input chunk. +// +// Call `push(newChunk)` to pass along transformed output +// to the readable side. You may call 'push' zero or more times. +// +// Call `cb(err)` when you are done with this chunk. If you pass +// an error, then that'll put the hurt on the whole operation. If you +// never call cb(), then you'll never get another chunk. +Transform.prototype._transform = function (chunk, encoding, cb) { + throw new Error('_transform() is not implemented'); +}; + +Transform.prototype._write = function (chunk, encoding, cb) { + var ts = this._transformState; + ts.writecb = cb; + ts.writechunk = chunk; + ts.writeencoding = encoding; + if (!ts.transforming) { + var rs = this._readableState; + if (ts.needTransform || rs.needReadable || rs.length < rs.highWaterMark) this._read(rs.highWaterMark); + } +}; + +// Doesn't matter what the args are here. +// _transform does all the work. +// That we got here means that the readable side wants more data. +Transform.prototype._read = function (n) { + var ts = this._transformState; + + if (ts.writechunk !== null && ts.writecb && !ts.transforming) { + ts.transforming = true; + this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform); + } else { + // mark that we need a transform, so that any data that comes in + // will get processed, now that we've asked for it. + ts.needTransform = true; + } +}; + +Transform.prototype._destroy = function (err, cb) { + var _this2 = this; + + Duplex.prototype._destroy.call(this, err, function (err2) { + cb(err2); + _this2.emit('close'); + }); +}; + +function done(stream, er, data) { + if (er) return stream.emit('error', er); + + if (data != null) // single equals check for both `null` and `undefined` + stream.push(data); + + // if there's nothing in the write buffer, then that means + // that nothing more will ever be provided + if (stream._writableState.length) throw new Error('Calling transform done when ws.length != 0'); + + if (stream._transformState.transforming) throw new Error('Calling transform done when still transforming'); + + return stream.push(null); +} +},{"./_stream_duplex":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_duplex.js","core-util-is":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/core-util-is/lib/util.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_writable.js":[function(require,module,exports){ +(function (process,global,setImmediate){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// A bit simpler than readable streams. +// Implement an async ._write(chunk, encoding, cb), and it'll handle all +// the drain event emission and buffering. + +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +module.exports = Writable; + +/* */ +function WriteReq(chunk, encoding, cb) { + this.chunk = chunk; + this.encoding = encoding; + this.callback = cb; + this.next = null; +} + +// It seems a linked list but it is not +// there will be only 2 of these for each stream +function CorkedRequest(state) { + var _this = this; + + this.next = null; + this.entry = null; + this.finish = function () { + onCorkedFinish(_this, state); + }; +} +/* */ + +/**/ +var asyncWrite = !process.browser && ['v0.10', 'v0.9.'].indexOf(process.version.slice(0, 5)) > -1 ? setImmediate : pna.nextTick; +/**/ + +/**/ +var Duplex; +/**/ + +Writable.WritableState = WritableState; + +/**/ +var util = require('core-util-is'); +util.inherits = require('inherits'); +/**/ + +/**/ +var internalUtil = { + deprecate: require('util-deprecate') +}; +/**/ + +/**/ +var Stream = require('./internal/streams/stream'); +/**/ + +/**/ + +var Buffer = require('safe-buffer').Buffer; +var OurUint8Array = global.Uint8Array || function () {}; +function _uint8ArrayToBuffer(chunk) { + return Buffer.from(chunk); +} +function _isUint8Array(obj) { + return Buffer.isBuffer(obj) || obj instanceof OurUint8Array; +} + +/**/ + +var destroyImpl = require('./internal/streams/destroy'); + +util.inherits(Writable, Stream); + +function nop() {} + +function WritableState(options, stream) { + Duplex = Duplex || require('./_stream_duplex'); + + options = options || {}; + + // Duplex streams are both readable and writable, but share + // the same options object. + // However, some cases require setting options to different + // values for the readable and the writable sides of the duplex stream. + // These options can be provided separately as readableXXX and writableXXX. + var isDuplex = stream instanceof Duplex; + + // object stream flag to indicate whether or not this stream + // contains buffers or objects. + this.objectMode = !!options.objectMode; + + if (isDuplex) this.objectMode = this.objectMode || !!options.writableObjectMode; + + // the point at which write() starts returning false + // Note: 0 is a valid value, means that we always return false if + // the entire buffer is not flushed immediately on write() + var hwm = options.highWaterMark; + var writableHwm = options.writableHighWaterMark; + var defaultHwm = this.objectMode ? 16 : 16 * 1024; + + if (hwm || hwm === 0) this.highWaterMark = hwm;else if (isDuplex && (writableHwm || writableHwm === 0)) this.highWaterMark = writableHwm;else this.highWaterMark = defaultHwm; + + // cast to ints. + this.highWaterMark = Math.floor(this.highWaterMark); + + // if _final has been called + this.finalCalled = false; + + // drain event flag. + this.needDrain = false; + // at the start of calling end() + this.ending = false; + // when end() has been called, and returned + this.ended = false; + // when 'finish' is emitted + this.finished = false; + + // has it been destroyed + this.destroyed = false; + + // should we decode strings into buffers before passing to _write? + // this is here so that some node-core streams can optimize string + // handling at a lower level. + var noDecode = options.decodeStrings === false; + this.decodeStrings = !noDecode; + + // Crypto is kind of old and crusty. Historically, its default string + // encoding is 'binary' so we have to make this configurable. + // Everything else in the universe uses 'utf8', though. + this.defaultEncoding = options.defaultEncoding || 'utf8'; + + // not an actual buffer we keep track of, but a measurement + // of how much we're waiting to get pushed to some underlying + // socket or file. + this.length = 0; + + // a flag to see when we're in the middle of a write. + this.writing = false; + + // when true all writes will be buffered until .uncork() call + this.corked = 0; + + // a flag to be able to tell if the onwrite cb is called immediately, + // or on a later tick. We set this to true at first, because any + // actions that shouldn't happen until "later" should generally also + // not happen before the first write call. + this.sync = true; + + // a flag to know if we're processing previously buffered items, which + // may call the _write() callback in the same tick, so that we don't + // end up in an overlapped onwrite situation. + this.bufferProcessing = false; + + // the callback that's passed to _write(chunk,cb) + this.onwrite = function (er) { + onwrite(stream, er); + }; + + // the callback that the user supplies to write(chunk,encoding,cb) + this.writecb = null; + + // the amount that is being written when _write is called. + this.writelen = 0; + + this.bufferedRequest = null; + this.lastBufferedRequest = null; + + // number of pending user-supplied write callbacks + // this must be 0 before 'finish' can be emitted + this.pendingcb = 0; + + // emit prefinish if the only thing we're waiting for is _write cbs + // This is relevant for synchronous Transform streams + this.prefinished = false; + + // True if the error was already emitted and should not be thrown again + this.errorEmitted = false; + + // count buffered requests + this.bufferedRequestCount = 0; + + // allocate the first CorkedRequest, there is always + // one allocated and free to use, and we maintain at most two + this.corkedRequestsFree = new CorkedRequest(this); +} + +WritableState.prototype.getBuffer = function getBuffer() { + var current = this.bufferedRequest; + var out = []; + while (current) { + out.push(current); + current = current.next; + } + return out; +}; + +(function () { + try { + Object.defineProperty(WritableState.prototype, 'buffer', { + get: internalUtil.deprecate(function () { + return this.getBuffer(); + }, '_writableState.buffer is deprecated. Use _writableState.getBuffer ' + 'instead.', 'DEP0003') + }); + } catch (_) {} +})(); + +// Test _writableState for inheritance to account for Duplex streams, +// whose prototype chain only points to Readable. +var realHasInstance; +if (typeof Symbol === 'function' && Symbol.hasInstance && typeof Function.prototype[Symbol.hasInstance] === 'function') { + realHasInstance = Function.prototype[Symbol.hasInstance]; + Object.defineProperty(Writable, Symbol.hasInstance, { + value: function (object) { + if (realHasInstance.call(this, object)) return true; + if (this !== Writable) return false; + + return object && object._writableState instanceof WritableState; + } + }); +} else { + realHasInstance = function (object) { + return object instanceof this; + }; +} + +function Writable(options) { + Duplex = Duplex || require('./_stream_duplex'); + + // Writable ctor is applied to Duplexes, too. + // `realHasInstance` is necessary because using plain `instanceof` + // would return false, as no `_writableState` property is attached. + + // Trying to use the custom `instanceof` for Writable here will also break the + // Node.js LazyTransform implementation, which has a non-trivial getter for + // `_writableState` that would lead to infinite recursion. + if (!realHasInstance.call(Writable, this) && !(this instanceof Duplex)) { + return new Writable(options); + } + + this._writableState = new WritableState(options, this); + + // legacy. + this.writable = true; + + if (options) { + if (typeof options.write === 'function') this._write = options.write; + + if (typeof options.writev === 'function') this._writev = options.writev; + + if (typeof options.destroy === 'function') this._destroy = options.destroy; + + if (typeof options.final === 'function') this._final = options.final; + } + + Stream.call(this); +} + +// Otherwise people can pipe Writable streams, which is just wrong. +Writable.prototype.pipe = function () { + this.emit('error', new Error('Cannot pipe, not readable')); +}; + +function writeAfterEnd(stream, cb) { + var er = new Error('write after end'); + // TODO: defer error events consistently everywhere, not just the cb + stream.emit('error', er); + pna.nextTick(cb, er); +} + +// Checks that a user-supplied chunk is valid, especially for the particular +// mode the stream is in. Currently this means that `null` is never accepted +// and undefined/non-string values are only allowed in object mode. +function validChunk(stream, state, chunk, cb) { + var valid = true; + var er = false; + + if (chunk === null) { + er = new TypeError('May not write null values to stream'); + } else if (typeof chunk !== 'string' && chunk !== undefined && !state.objectMode) { + er = new TypeError('Invalid non-string/buffer chunk'); + } + if (er) { + stream.emit('error', er); + pna.nextTick(cb, er); + valid = false; + } + return valid; +} + +Writable.prototype.write = function (chunk, encoding, cb) { + var state = this._writableState; + var ret = false; + var isBuf = !state.objectMode && _isUint8Array(chunk); + + if (isBuf && !Buffer.isBuffer(chunk)) { + chunk = _uint8ArrayToBuffer(chunk); + } + + if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (isBuf) encoding = 'buffer';else if (!encoding) encoding = state.defaultEncoding; + + if (typeof cb !== 'function') cb = nop; + + if (state.ended) writeAfterEnd(this, cb);else if (isBuf || validChunk(this, state, chunk, cb)) { + state.pendingcb++; + ret = writeOrBuffer(this, state, isBuf, chunk, encoding, cb); + } + + return ret; +}; + +Writable.prototype.cork = function () { + var state = this._writableState; + + state.corked++; +}; + +Writable.prototype.uncork = function () { + var state = this._writableState; + + if (state.corked) { + state.corked--; + + if (!state.writing && !state.corked && !state.finished && !state.bufferProcessing && state.bufferedRequest) clearBuffer(this, state); + } +}; + +Writable.prototype.setDefaultEncoding = function setDefaultEncoding(encoding) { + // node::ParseEncoding() requires lower case. + if (typeof encoding === 'string') encoding = encoding.toLowerCase(); + if (!(['hex', 'utf8', 'utf-8', 'ascii', 'binary', 'base64', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le', 'raw'].indexOf((encoding + '').toLowerCase()) > -1)) throw new TypeError('Unknown encoding: ' + encoding); + this._writableState.defaultEncoding = encoding; + return this; +}; + +function decodeChunk(state, chunk, encoding) { + if (!state.objectMode && state.decodeStrings !== false && typeof chunk === 'string') { + chunk = Buffer.from(chunk, encoding); + } + return chunk; +} + +Object.defineProperty(Writable.prototype, 'writableHighWaterMark', { + // making it explicit this property is not enumerable + // because otherwise some prototype manipulation in + // userland will fail + enumerable: false, + get: function () { + return this._writableState.highWaterMark; + } +}); + +// if we're already writing something, then just put this +// in the queue, and wait our turn. Otherwise, call _write +// If we return false, then we need a drain event, so set that flag. +function writeOrBuffer(stream, state, isBuf, chunk, encoding, cb) { + if (!isBuf) { + var newChunk = decodeChunk(state, chunk, encoding); + if (chunk !== newChunk) { + isBuf = true; + encoding = 'buffer'; + chunk = newChunk; + } + } + var len = state.objectMode ? 1 : chunk.length; + + state.length += len; + + var ret = state.length < state.highWaterMark; + // we must ensure that previous needDrain will not be reset to false. + if (!ret) state.needDrain = true; + + if (state.writing || state.corked) { + var last = state.lastBufferedRequest; + state.lastBufferedRequest = { + chunk: chunk, + encoding: encoding, + isBuf: isBuf, + callback: cb, + next: null + }; + if (last) { + last.next = state.lastBufferedRequest; + } else { + state.bufferedRequest = state.lastBufferedRequest; + } + state.bufferedRequestCount += 1; + } else { + doWrite(stream, state, false, len, chunk, encoding, cb); + } + + return ret; +} + +function doWrite(stream, state, writev, len, chunk, encoding, cb) { + state.writelen = len; + state.writecb = cb; + state.writing = true; + state.sync = true; + if (writev) stream._writev(chunk, state.onwrite);else stream._write(chunk, encoding, state.onwrite); + state.sync = false; +} + +function onwriteError(stream, state, sync, er, cb) { + --state.pendingcb; + + if (sync) { + // defer the callback if we are being called synchronously + // to avoid piling up things on the stack + pna.nextTick(cb, er); + // this can emit finish, and it will always happen + // after error + pna.nextTick(finishMaybe, stream, state); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + } else { + // the caller expect this to happen before if + // it is async + cb(er); + stream._writableState.errorEmitted = true; + stream.emit('error', er); + // this can emit finish, but finish must + // always follow error + finishMaybe(stream, state); + } +} + +function onwriteStateUpdate(state) { + state.writing = false; + state.writecb = null; + state.length -= state.writelen; + state.writelen = 0; +} + +function onwrite(stream, er) { + var state = stream._writableState; + var sync = state.sync; + var cb = state.writecb; + + onwriteStateUpdate(state); + + if (er) onwriteError(stream, state, sync, er, cb);else { + // Check if we're actually ready to finish, but don't emit yet + var finished = needFinish(state); + + if (!finished && !state.corked && !state.bufferProcessing && state.bufferedRequest) { + clearBuffer(stream, state); + } + + if (sync) { + /**/ + asyncWrite(afterWrite, stream, state, finished, cb); + /**/ + } else { + afterWrite(stream, state, finished, cb); + } + } +} + +function afterWrite(stream, state, finished, cb) { + if (!finished) onwriteDrain(stream, state); + state.pendingcb--; + cb(); + finishMaybe(stream, state); +} + +// Must force callback to be called on nextTick, so that we don't +// emit 'drain' before the write() consumer gets the 'false' return +// value, and has a chance to attach a 'drain' listener. +function onwriteDrain(stream, state) { + if (state.length === 0 && state.needDrain) { + state.needDrain = false; + stream.emit('drain'); + } +} + +// if there's something in the buffer waiting, then process it +function clearBuffer(stream, state) { + state.bufferProcessing = true; + var entry = state.bufferedRequest; + + if (stream._writev && entry && entry.next) { + // Fast case, write everything using _writev() + var l = state.bufferedRequestCount; + var buffer = new Array(l); + var holder = state.corkedRequestsFree; + holder.entry = entry; + + var count = 0; + var allBuffers = true; + while (entry) { + buffer[count] = entry; + if (!entry.isBuf) allBuffers = false; + entry = entry.next; + count += 1; + } + buffer.allBuffers = allBuffers; + + doWrite(stream, state, true, state.length, buffer, '', holder.finish); + + // doWrite is almost always async, defer these to save a bit of time + // as the hot path ends with doWrite + state.pendingcb++; + state.lastBufferedRequest = null; + if (holder.next) { + state.corkedRequestsFree = holder.next; + holder.next = null; + } else { + state.corkedRequestsFree = new CorkedRequest(state); + } + state.bufferedRequestCount = 0; + } else { + // Slow case, write chunks one-by-one + while (entry) { + var chunk = entry.chunk; + var encoding = entry.encoding; + var cb = entry.callback; + var len = state.objectMode ? 1 : chunk.length; + + doWrite(stream, state, false, len, chunk, encoding, cb); + entry = entry.next; + state.bufferedRequestCount--; + // if we didn't call the onwrite immediately, then + // it means that we need to wait until it does. + // also, that means that the chunk and cb are currently + // being processed, so move the buffer counter past them. + if (state.writing) { + break; + } + } + + if (entry === null) state.lastBufferedRequest = null; + } + + state.bufferedRequest = entry; + state.bufferProcessing = false; +} + +Writable.prototype._write = function (chunk, encoding, cb) { + cb(new Error('_write() is not implemented')); +}; + +Writable.prototype._writev = null; + +Writable.prototype.end = function (chunk, encoding, cb) { + var state = this._writableState; + + if (typeof chunk === 'function') { + cb = chunk; + chunk = null; + encoding = null; + } else if (typeof encoding === 'function') { + cb = encoding; + encoding = null; + } + + if (chunk !== null && chunk !== undefined) this.write(chunk, encoding); + + // .end() fully uncorks + if (state.corked) { + state.corked = 1; + this.uncork(); + } + + // ignore unnecessary end() calls. + if (!state.ending && !state.finished) endWritable(this, state, cb); +}; + +function needFinish(state) { + return state.ending && state.length === 0 && state.bufferedRequest === null && !state.finished && !state.writing; +} +function callFinal(stream, state) { + stream._final(function (err) { + state.pendingcb--; + if (err) { + stream.emit('error', err); + } + state.prefinished = true; + stream.emit('prefinish'); + finishMaybe(stream, state); + }); +} +function prefinish(stream, state) { + if (!state.prefinished && !state.finalCalled) { + if (typeof stream._final === 'function') { + state.pendingcb++; + state.finalCalled = true; + pna.nextTick(callFinal, stream, state); + } else { + state.prefinished = true; + stream.emit('prefinish'); + } + } +} + +function finishMaybe(stream, state) { + var need = needFinish(state); + if (need) { + prefinish(stream, state); + if (state.pendingcb === 0) { + state.finished = true; + stream.emit('finish'); + } + } + return need; +} + +function endWritable(stream, state, cb) { + state.ending = true; + finishMaybe(stream, state); + if (cb) { + if (state.finished) pna.nextTick(cb);else stream.once('finish', cb); + } + state.ended = true; + stream.writable = false; +} + +function onCorkedFinish(corkReq, state, err) { + var entry = corkReq.entry; + corkReq.entry = null; + while (entry) { + var cb = entry.callback; + state.pendingcb--; + cb(err); + entry = entry.next; + } + if (state.corkedRequestsFree) { + state.corkedRequestsFree.next = corkReq; + } else { + state.corkedRequestsFree = corkReq; + } +} + +Object.defineProperty(Writable.prototype, 'destroyed', { + get: function () { + if (this._writableState === undefined) { + return false; + } + return this._writableState.destroyed; + }, + set: function (value) { + // we ignore the value if the stream + // has not been initialized yet + if (!this._writableState) { + return; + } + + // backward compatibility, the user is explicitly + // managing destroyed + this._writableState.destroyed = value; + } +}); + +Writable.prototype.destroy = destroyImpl.destroy; +Writable.prototype._undestroy = destroyImpl.undestroy; +Writable.prototype._destroy = function (err, cb) { + this.end(); + cb(err); +}; +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {},require("timers").setImmediate) + +},{"./_stream_duplex":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_duplex.js","./internal/streams/destroy":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/destroy.js","./internal/streams/stream":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/stream-browser.js","_process":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js","core-util-is":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/core-util-is/lib/util.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","process-nextick-args":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process-nextick-args/index.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js","timers":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/timers-browserify/main.js","util-deprecate":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/util-deprecate/browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/BufferList.js":[function(require,module,exports){ +'use strict'; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Buffer = require('safe-buffer').Buffer; +var util = require('util'); + +function copyBuffer(src, target, offset) { + src.copy(target, offset); +} + +module.exports = function () { + function BufferList() { + _classCallCheck(this, BufferList); + + this.head = null; + this.tail = null; + this.length = 0; + } + + BufferList.prototype.push = function push(v) { + var entry = { data: v, next: null }; + if (this.length > 0) this.tail.next = entry;else this.head = entry; + this.tail = entry; + ++this.length; + }; + + BufferList.prototype.unshift = function unshift(v) { + var entry = { data: v, next: this.head }; + if (this.length === 0) this.tail = entry; + this.head = entry; + ++this.length; + }; + + BufferList.prototype.shift = function shift() { + if (this.length === 0) return; + var ret = this.head.data; + if (this.length === 1) this.head = this.tail = null;else this.head = this.head.next; + --this.length; + return ret; + }; + + BufferList.prototype.clear = function clear() { + this.head = this.tail = null; + this.length = 0; + }; + + BufferList.prototype.join = function join(s) { + if (this.length === 0) return ''; + var p = this.head; + var ret = '' + p.data; + while (p = p.next) { + ret += s + p.data; + }return ret; + }; + + BufferList.prototype.concat = function concat(n) { + if (this.length === 0) return Buffer.alloc(0); + if (this.length === 1) return this.head.data; + var ret = Buffer.allocUnsafe(n >>> 0); + var p = this.head; + var i = 0; + while (p) { + copyBuffer(p.data, ret, i); + i += p.data.length; + p = p.next; + } + return ret; + }; + + return BufferList; +}(); + +if (util && util.inspect && util.inspect.custom) { + module.exports.prototype[util.inspect.custom] = function () { + var obj = util.inspect({ length: this.length }); + return this.constructor.name + ' ' + obj; + }; +} +},{"safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js","util":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browser-resolve/empty.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/destroy.js":[function(require,module,exports){ +'use strict'; + +/**/ + +var pna = require('process-nextick-args'); +/**/ + +// undocumented cb() API, needed for core, not for public API +function destroy(err, cb) { + var _this = this; + + var readableDestroyed = this._readableState && this._readableState.destroyed; + var writableDestroyed = this._writableState && this._writableState.destroyed; + + if (readableDestroyed || writableDestroyed) { + if (cb) { + cb(err); + } else if (err && (!this._writableState || !this._writableState.errorEmitted)) { + pna.nextTick(emitErrorNT, this, err); + } + return this; + } + + // we set destroyed to true before firing error callbacks in order + // to make it re-entrance safe in case destroy() is called within callbacks + + if (this._readableState) { + this._readableState.destroyed = true; + } + + // if this is a duplex stream mark the writable part as destroyed as well + if (this._writableState) { + this._writableState.destroyed = true; + } + + this._destroy(err || null, function (err) { + if (!cb && err) { + pna.nextTick(emitErrorNT, _this, err); + if (_this._writableState) { + _this._writableState.errorEmitted = true; + } + } else if (cb) { + cb(err); + } + }); + + return this; +} + +function undestroy() { + if (this._readableState) { + this._readableState.destroyed = false; + this._readableState.reading = false; + this._readableState.ended = false; + this._readableState.endEmitted = false; + } + + if (this._writableState) { + this._writableState.destroyed = false; + this._writableState.ended = false; + this._writableState.ending = false; + this._writableState.finished = false; + this._writableState.errorEmitted = false; + } +} + +function emitErrorNT(self, err) { + self.emit('error', err); +} + +module.exports = { + destroy: destroy, + undestroy: undestroy +}; +},{"process-nextick-args":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process-nextick-args/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/stream-browser.js":[function(require,module,exports){ +module.exports = require('events').EventEmitter; + +},{"events":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/events/events.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/passthrough.js":[function(require,module,exports){ +module.exports = require('./readable').PassThrough + +},{"./readable":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/readable-browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/readable-browser.js":[function(require,module,exports){ +exports = module.exports = require('./lib/_stream_readable.js'); +exports.Stream = exports; +exports.Readable = exports; +exports.Writable = require('./lib/_stream_writable.js'); +exports.Duplex = require('./lib/_stream_duplex.js'); +exports.Transform = require('./lib/_stream_transform.js'); +exports.PassThrough = require('./lib/_stream_passthrough.js'); + +},{"./lib/_stream_duplex.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_duplex.js","./lib/_stream_passthrough.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_passthrough.js","./lib/_stream_readable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_readable.js","./lib/_stream_transform.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_transform.js","./lib/_stream_writable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_writable.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/transform.js":[function(require,module,exports){ +module.exports = require('./readable').Transform + +},{"./readable":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/readable-browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/writable-browser.js":[function(require,module,exports){ +module.exports = require('./lib/_stream_writable.js'); + +},{"./lib/_stream_writable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_writable.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ripemd160/index.js":[function(require,module,exports){ +'use strict' +var Buffer = require('buffer').Buffer +var inherits = require('inherits') +var HashBase = require('hash-base') + +var ARRAY16 = new Array(16) + +var zl = [ + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, + 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, + 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, + 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13 +] + +var zr = [ + 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, + 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, + 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, + 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, + 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11 +] + +var sl = [ + 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, + 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, + 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, + 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, + 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6 +] + +var sr = [ + 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, + 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, + 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, + 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, + 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11 +] + +var hl = [0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e] +var hr = [0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000] + +function RIPEMD160 () { + HashBase.call(this, 64) + + // state + this._a = 0x67452301 + this._b = 0xefcdab89 + this._c = 0x98badcfe + this._d = 0x10325476 + this._e = 0xc3d2e1f0 +} + +inherits(RIPEMD160, HashBase) + +RIPEMD160.prototype._update = function () { + var words = ARRAY16 + for (var j = 0; j < 16; ++j) words[j] = this._block.readInt32LE(j * 4) + + var al = this._a | 0 + var bl = this._b | 0 + var cl = this._c | 0 + var dl = this._d | 0 + var el = this._e | 0 + + var ar = this._a | 0 + var br = this._b | 0 + var cr = this._c | 0 + var dr = this._d | 0 + var er = this._e | 0 + + // computation + for (var i = 0; i < 80; i += 1) { + var tl + var tr + if (i < 16) { + tl = fn1(al, bl, cl, dl, el, words[zl[i]], hl[0], sl[i]) + tr = fn5(ar, br, cr, dr, er, words[zr[i]], hr[0], sr[i]) + } else if (i < 32) { + tl = fn2(al, bl, cl, dl, el, words[zl[i]], hl[1], sl[i]) + tr = fn4(ar, br, cr, dr, er, words[zr[i]], hr[1], sr[i]) + } else if (i < 48) { + tl = fn3(al, bl, cl, dl, el, words[zl[i]], hl[2], sl[i]) + tr = fn3(ar, br, cr, dr, er, words[zr[i]], hr[2], sr[i]) + } else if (i < 64) { + tl = fn4(al, bl, cl, dl, el, words[zl[i]], hl[3], sl[i]) + tr = fn2(ar, br, cr, dr, er, words[zr[i]], hr[3], sr[i]) + } else { // if (i<80) { + tl = fn5(al, bl, cl, dl, el, words[zl[i]], hl[4], sl[i]) + tr = fn1(ar, br, cr, dr, er, words[zr[i]], hr[4], sr[i]) + } + + al = el + el = dl + dl = rotl(cl, 10) + cl = bl + bl = tl + + ar = er + er = dr + dr = rotl(cr, 10) + cr = br + br = tr + } + + // update state + var t = (this._b + cl + dr) | 0 + this._b = (this._c + dl + er) | 0 + this._c = (this._d + el + ar) | 0 + this._d = (this._e + al + br) | 0 + this._e = (this._a + bl + cr) | 0 + this._a = t +} + +RIPEMD160.prototype._digest = function () { + // create padding and handle blocks + this._block[this._blockOffset++] = 0x80 + if (this._blockOffset > 56) { + this._block.fill(0, this._blockOffset, 64) + this._update() + this._blockOffset = 0 + } + + this._block.fill(0, this._blockOffset, 56) + this._block.writeUInt32LE(this._length[0], 56) + this._block.writeUInt32LE(this._length[1], 60) + this._update() + + // produce result + var buffer = Buffer.alloc ? Buffer.alloc(20) : new Buffer(20) + buffer.writeInt32LE(this._a, 0) + buffer.writeInt32LE(this._b, 4) + buffer.writeInt32LE(this._c, 8) + buffer.writeInt32LE(this._d, 12) + buffer.writeInt32LE(this._e, 16) + return buffer +} + +function rotl (x, n) { + return (x << n) | (x >>> (32 - n)) +} + +function fn1 (a, b, c, d, e, m, k, s) { + return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + e) | 0 +} + +function fn2 (a, b, c, d, e, m, k, s) { + return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + e) | 0 +} + +function fn3 (a, b, c, d, e, m, k, s) { + return (rotl((a + ((b | (~c)) ^ d) + m + k) | 0, s) + e) | 0 +} + +function fn4 (a, b, c, d, e, m, k, s) { + return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + e) | 0 +} + +function fn5 (a, b, c, d, e, m, k, s) { + return (rotl((a + (b ^ (c | (~d))) + m + k) | 0, s) + e) | 0 +} + +module.exports = RIPEMD160 + +},{"buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","hash-base":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/hash-base/index.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js":[function(require,module,exports){ +/* eslint-disable node/no-deprecated-api */ +var buffer = require('buffer') +var Buffer = buffer.Buffer + +// alternative to using Object.keys for old browsers +function copyProps (src, dst) { + for (var key in src) { + dst[key] = src[key] + } +} +if (Buffer.from && Buffer.alloc && Buffer.allocUnsafe && Buffer.allocUnsafeSlow) { + module.exports = buffer +} else { + // Copy properties from require('buffer') + copyProps(buffer, exports) + exports.Buffer = SafeBuffer +} + +function SafeBuffer (arg, encodingOrOffset, length) { + return Buffer(arg, encodingOrOffset, length) +} + +// Copy static methods from Buffer +copyProps(Buffer, SafeBuffer) + +SafeBuffer.from = function (arg, encodingOrOffset, length) { + if (typeof arg === 'number') { + throw new TypeError('Argument must not be a number') + } + return Buffer(arg, encodingOrOffset, length) +} + +SafeBuffer.alloc = function (size, fill, encoding) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + var buf = Buffer(size) + if (fill !== undefined) { + if (typeof encoding === 'string') { + buf.fill(fill, encoding) + } else { + buf.fill(fill) + } + } else { + buf.fill(0) + } + return buf +} + +SafeBuffer.allocUnsafe = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return Buffer(size) +} + +SafeBuffer.allocUnsafeSlow = function (size) { + if (typeof size !== 'number') { + throw new TypeError('Argument must be a number') + } + return buffer.SlowBuffer(size) +} + +},{"buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/secure-random/lib/secure-random.js":[function(require,module,exports){ +(function (process,Buffer){ +!function(globals){ +'use strict' + +//*** UMD BEGIN +if (typeof define !== 'undefined' && define.amd) { //require.js / AMD + define([], function() { + return secureRandom + }) +} else if (typeof module !== 'undefined' && module.exports) { //CommonJS + module.exports = secureRandom +} else { //script / browser + globals.secureRandom = secureRandom +} +//*** UMD END + +//options.type is the only valid option +function secureRandom(count, options) { + options = options || {type: 'Array'} + //we check for process.pid to prevent browserify from tricking us + if (typeof process != 'undefined' && typeof process.pid == 'number') { + return nodeRandom(count, options) + } else { + var crypto = window.crypto || window.msCrypto + if (!crypto) throw new Error("Your browser does not support window.crypto.") + return browserRandom(count, options) + } +} + +function nodeRandom(count, options) { + var crypto = require('crypto') + var buf = crypto.randomBytes(count) + + switch (options.type) { + case 'Array': + return [].slice.call(buf) + case 'Buffer': + return buf + case 'Uint8Array': + var arr = new Uint8Array(count) + for (var i = 0; i < count; ++i) { arr[i] = buf.readUInt8(i) } + return arr + default: + throw new Error(options.type + " is unsupported.") + } +} + +function browserRandom(count, options) { + var nativeArr = new Uint8Array(count) + var crypto = window.crypto || window.msCrypto + crypto.getRandomValues(nativeArr) + + switch (options.type) { + case 'Array': + return [].slice.call(nativeArr) + case 'Buffer': + try { var b = new Buffer(1) } catch(e) { throw new Error('Buffer not supported in this environment. Use Node.js or Browserify for browser support.')} + return new Buffer(nativeArr) + case 'Uint8Array': + return nativeArr + default: + throw new Error(options.type + " is unsupported.") + } +} + +secureRandom.randomArray = function(byteCount) { + return secureRandom(byteCount, {type: 'Array'}) +} + +secureRandom.randomUint8Array = function(byteCount) { + return secureRandom(byteCount, {type: 'Uint8Array'}) +} + +secureRandom.randomBuffer = function(byteCount) { + return secureRandom(byteCount, {type: 'Buffer'}) +} + + +}(this); + +}).call(this,require('_process'),require("buffer").Buffer) + +},{"_process":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js","buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js","crypto":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browser-resolve/empty.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js":[function(require,module,exports){ +var Buffer = require('safe-buffer').Buffer + +// prototype class for hash functions +function Hash (blockSize, finalSize) { + this._block = Buffer.alloc(blockSize) + this._finalSize = finalSize + this._blockSize = blockSize + this._len = 0 +} + +Hash.prototype.update = function (data, enc) { + if (typeof data === 'string') { + enc = enc || 'utf8' + data = Buffer.from(data, enc) + } + + var block = this._block + var blockSize = this._blockSize + var length = data.length + var accum = this._len + + for (var offset = 0; offset < length;) { + var assigned = accum % blockSize + var remainder = Math.min(length - offset, blockSize - assigned) + + for (var i = 0; i < remainder; i++) { + block[assigned + i] = data[offset + i] + } + + accum += remainder + offset += remainder + + if ((accum % blockSize) === 0) { + this._update(block) + } + } + + this._len += length + return this +} + +Hash.prototype.digest = function (enc) { + var rem = this._len % this._blockSize + + this._block[rem] = 0x80 + + // zero (rem + 1) trailing bits, where (rem + 1) is the smallest + // non-negative solution to the equation (length + 1 + (rem + 1)) === finalSize mod blockSize + this._block.fill(0, rem + 1) + + if (rem >= this._finalSize) { + this._update(this._block) + this._block.fill(0) + } + + var bits = this._len * 8 + + // uint32 + if (bits <= 0xffffffff) { + this._block.writeUInt32BE(bits, this._blockSize - 4) + + // uint64 + } else { + var lowBits = (bits & 0xffffffff) >>> 0 + var highBits = (bits - lowBits) / 0x100000000 + + this._block.writeUInt32BE(highBits, this._blockSize - 8) + this._block.writeUInt32BE(lowBits, this._blockSize - 4) + } + + this._update(this._block) + var hash = this._hash() + + return enc ? hash.toString(enc) : hash +} + +Hash.prototype._update = function () { + throw new Error('_update must be implemented by subclass') +} + +module.exports = Hash + +},{"safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/index.js":[function(require,module,exports){ +var exports = module.exports = function SHA (algorithm) { + algorithm = algorithm.toLowerCase() + + var Algorithm = exports[algorithm] + if (!Algorithm) throw new Error(algorithm + ' is not supported (we accept pull requests)') + + return new Algorithm() +} + +exports.sha = require('./sha') +exports.sha1 = require('./sha1') +exports.sha224 = require('./sha224') +exports.sha256 = require('./sha256') +exports.sha384 = require('./sha384') +exports.sha512 = require('./sha512') + +},{"./sha":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha.js","./sha1":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha1.js","./sha224":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha224.js","./sha256":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha256.js","./sha384":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha384.js","./sha512":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha512.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha.js":[function(require,module,exports){ +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-0, as defined + * in FIPS PUB 180-1 + * This source code is derived from sha1.js of the same repository. + * The difference between SHA-0 and SHA-1 is just a bitwise rotate left + * operation was added. + */ + +var inherits = require('inherits') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer + +var K = [ + 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0 +] + +var W = new Array(80) + +function Sha () { + this.init() + this._w = W + + Hash.call(this, 64, 56) +} + +inherits(Sha, Hash) + +Sha.prototype.init = function () { + this._a = 0x67452301 + this._b = 0xefcdab89 + this._c = 0x98badcfe + this._d = 0x10325476 + this._e = 0xc3d2e1f0 + + return this +} + +function rotl5 (num) { + return (num << 5) | (num >>> 27) +} + +function rotl30 (num) { + return (num << 30) | (num >>> 2) +} + +function ft (s, b, c, d) { + if (s === 0) return (b & c) | ((~b) & d) + if (s === 2) return (b & c) | (b & d) | (c & d) + return b ^ c ^ d +} + +Sha.prototype._update = function (M) { + var W = this._w + + var a = this._a | 0 + var b = this._b | 0 + var c = this._c | 0 + var d = this._d | 0 + var e = this._e | 0 + + for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) + for (; i < 80; ++i) W[i] = W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16] + + for (var j = 0; j < 80; ++j) { + var s = ~~(j / 20) + var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0 + + e = d + d = c + c = rotl30(b) + b = a + a = t + } + + this._a = (a + this._a) | 0 + this._b = (b + this._b) | 0 + this._c = (c + this._c) | 0 + this._d = (d + this._d) | 0 + this._e = (e + this._e) | 0 +} + +Sha.prototype._hash = function () { + var H = Buffer.allocUnsafe(20) + + H.writeInt32BE(this._a | 0, 0) + H.writeInt32BE(this._b | 0, 4) + H.writeInt32BE(this._c | 0, 8) + H.writeInt32BE(this._d | 0, 12) + H.writeInt32BE(this._e | 0, 16) + + return H +} + +module.exports = Sha + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha1.js":[function(require,module,exports){ +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined + * in FIPS PUB 180-1 + * Version 2.1a Copyright Paul Johnston 2000 - 2002. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + */ + +var inherits = require('inherits') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer + +var K = [ + 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc | 0, 0xca62c1d6 | 0 +] + +var W = new Array(80) + +function Sha1 () { + this.init() + this._w = W + + Hash.call(this, 64, 56) +} + +inherits(Sha1, Hash) + +Sha1.prototype.init = function () { + this._a = 0x67452301 + this._b = 0xefcdab89 + this._c = 0x98badcfe + this._d = 0x10325476 + this._e = 0xc3d2e1f0 + + return this +} + +function rotl1 (num) { + return (num << 1) | (num >>> 31) +} + +function rotl5 (num) { + return (num << 5) | (num >>> 27) +} + +function rotl30 (num) { + return (num << 30) | (num >>> 2) +} + +function ft (s, b, c, d) { + if (s === 0) return (b & c) | ((~b) & d) + if (s === 2) return (b & c) | (b & d) | (c & d) + return b ^ c ^ d +} + +Sha1.prototype._update = function (M) { + var W = this._w + + var a = this._a | 0 + var b = this._b | 0 + var c = this._c | 0 + var d = this._d | 0 + var e = this._e | 0 + + for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) + for (; i < 80; ++i) W[i] = rotl1(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16]) + + for (var j = 0; j < 80; ++j) { + var s = ~~(j / 20) + var t = (rotl5(a) + ft(s, b, c, d) + e + W[j] + K[s]) | 0 + + e = d + d = c + c = rotl30(b) + b = a + a = t + } + + this._a = (a + this._a) | 0 + this._b = (b + this._b) | 0 + this._c = (c + this._c) | 0 + this._d = (d + this._d) | 0 + this._e = (e + this._e) | 0 +} + +Sha1.prototype._hash = function () { + var H = Buffer.allocUnsafe(20) + + H.writeInt32BE(this._a | 0, 0) + H.writeInt32BE(this._b | 0, 4) + H.writeInt32BE(this._c | 0, 8) + H.writeInt32BE(this._d | 0, 12) + H.writeInt32BE(this._e | 0, 16) + + return H +} + +module.exports = Sha1 + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha224.js":[function(require,module,exports){ +/** + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined + * in FIPS 180-2 + * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * + */ + +var inherits = require('inherits') +var Sha256 = require('./sha256') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer + +var W = new Array(64) + +function Sha224 () { + this.init() + + this._w = W // new Array(64) + + Hash.call(this, 64, 56) +} + +inherits(Sha224, Sha256) + +Sha224.prototype.init = function () { + this._a = 0xc1059ed8 + this._b = 0x367cd507 + this._c = 0x3070dd17 + this._d = 0xf70e5939 + this._e = 0xffc00b31 + this._f = 0x68581511 + this._g = 0x64f98fa7 + this._h = 0xbefa4fa4 + + return this +} + +Sha224.prototype._hash = function () { + var H = Buffer.allocUnsafe(28) + + H.writeInt32BE(this._a, 0) + H.writeInt32BE(this._b, 4) + H.writeInt32BE(this._c, 8) + H.writeInt32BE(this._d, 12) + H.writeInt32BE(this._e, 16) + H.writeInt32BE(this._f, 20) + H.writeInt32BE(this._g, 24) + + return H +} + +module.exports = Sha224 + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js","./sha256":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha256.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha256.js":[function(require,module,exports){ +/** + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined + * in FIPS 180-2 + * Version 2.2-beta Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * + */ + +var inherits = require('inherits') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer + +var K = [ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2 +] + +var W = new Array(64) + +function Sha256 () { + this.init() + + this._w = W // new Array(64) + + Hash.call(this, 64, 56) +} + +inherits(Sha256, Hash) + +Sha256.prototype.init = function () { + this._a = 0x6a09e667 + this._b = 0xbb67ae85 + this._c = 0x3c6ef372 + this._d = 0xa54ff53a + this._e = 0x510e527f + this._f = 0x9b05688c + this._g = 0x1f83d9ab + this._h = 0x5be0cd19 + + return this +} + +function ch (x, y, z) { + return z ^ (x & (y ^ z)) +} + +function maj (x, y, z) { + return (x & y) | (z & (x | y)) +} + +function sigma0 (x) { + return (x >>> 2 | x << 30) ^ (x >>> 13 | x << 19) ^ (x >>> 22 | x << 10) +} + +function sigma1 (x) { + return (x >>> 6 | x << 26) ^ (x >>> 11 | x << 21) ^ (x >>> 25 | x << 7) +} + +function gamma0 (x) { + return (x >>> 7 | x << 25) ^ (x >>> 18 | x << 14) ^ (x >>> 3) +} + +function gamma1 (x) { + return (x >>> 17 | x << 15) ^ (x >>> 19 | x << 13) ^ (x >>> 10) +} + +Sha256.prototype._update = function (M) { + var W = this._w + + var a = this._a | 0 + var b = this._b | 0 + var c = this._c | 0 + var d = this._d | 0 + var e = this._e | 0 + var f = this._f | 0 + var g = this._g | 0 + var h = this._h | 0 + + for (var i = 0; i < 16; ++i) W[i] = M.readInt32BE(i * 4) + for (; i < 64; ++i) W[i] = (gamma1(W[i - 2]) + W[i - 7] + gamma0(W[i - 15]) + W[i - 16]) | 0 + + for (var j = 0; j < 64; ++j) { + var T1 = (h + sigma1(e) + ch(e, f, g) + K[j] + W[j]) | 0 + var T2 = (sigma0(a) + maj(a, b, c)) | 0 + + h = g + g = f + f = e + e = (d + T1) | 0 + d = c + c = b + b = a + a = (T1 + T2) | 0 + } + + this._a = (a + this._a) | 0 + this._b = (b + this._b) | 0 + this._c = (c + this._c) | 0 + this._d = (d + this._d) | 0 + this._e = (e + this._e) | 0 + this._f = (f + this._f) | 0 + this._g = (g + this._g) | 0 + this._h = (h + this._h) | 0 +} + +Sha256.prototype._hash = function () { + var H = Buffer.allocUnsafe(32) + + H.writeInt32BE(this._a, 0) + H.writeInt32BE(this._b, 4) + H.writeInt32BE(this._c, 8) + H.writeInt32BE(this._d, 12) + H.writeInt32BE(this._e, 16) + H.writeInt32BE(this._f, 20) + H.writeInt32BE(this._g, 24) + H.writeInt32BE(this._h, 28) + + return H +} + +module.exports = Sha256 + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha384.js":[function(require,module,exports){ +var inherits = require('inherits') +var SHA512 = require('./sha512') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer + +var W = new Array(160) + +function Sha384 () { + this.init() + this._w = W + + Hash.call(this, 128, 112) +} + +inherits(Sha384, SHA512) + +Sha384.prototype.init = function () { + this._ah = 0xcbbb9d5d + this._bh = 0x629a292a + this._ch = 0x9159015a + this._dh = 0x152fecd8 + this._eh = 0x67332667 + this._fh = 0x8eb44a87 + this._gh = 0xdb0c2e0d + this._hh = 0x47b5481d + + this._al = 0xc1059ed8 + this._bl = 0x367cd507 + this._cl = 0x3070dd17 + this._dl = 0xf70e5939 + this._el = 0xffc00b31 + this._fl = 0x68581511 + this._gl = 0x64f98fa7 + this._hl = 0xbefa4fa4 + + return this +} + +Sha384.prototype._hash = function () { + var H = Buffer.allocUnsafe(48) + + function writeInt64BE (h, l, offset) { + H.writeInt32BE(h, offset) + H.writeInt32BE(l, offset + 4) + } + + writeInt64BE(this._ah, this._al, 0) + writeInt64BE(this._bh, this._bl, 8) + writeInt64BE(this._ch, this._cl, 16) + writeInt64BE(this._dh, this._dl, 24) + writeInt64BE(this._eh, this._el, 32) + writeInt64BE(this._fh, this._fl, 40) + + return H +} + +module.exports = Sha384 + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js","./sha512":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha512.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha512.js":[function(require,module,exports){ +var inherits = require('inherits') +var Hash = require('./hash') +var Buffer = require('safe-buffer').Buffer + +var K = [ + 0x428a2f98, 0xd728ae22, 0x71374491, 0x23ef65cd, + 0xb5c0fbcf, 0xec4d3b2f, 0xe9b5dba5, 0x8189dbbc, + 0x3956c25b, 0xf348b538, 0x59f111f1, 0xb605d019, + 0x923f82a4, 0xaf194f9b, 0xab1c5ed5, 0xda6d8118, + 0xd807aa98, 0xa3030242, 0x12835b01, 0x45706fbe, + 0x243185be, 0x4ee4b28c, 0x550c7dc3, 0xd5ffb4e2, + 0x72be5d74, 0xf27b896f, 0x80deb1fe, 0x3b1696b1, + 0x9bdc06a7, 0x25c71235, 0xc19bf174, 0xcf692694, + 0xe49b69c1, 0x9ef14ad2, 0xefbe4786, 0x384f25e3, + 0x0fc19dc6, 0x8b8cd5b5, 0x240ca1cc, 0x77ac9c65, + 0x2de92c6f, 0x592b0275, 0x4a7484aa, 0x6ea6e483, + 0x5cb0a9dc, 0xbd41fbd4, 0x76f988da, 0x831153b5, + 0x983e5152, 0xee66dfab, 0xa831c66d, 0x2db43210, + 0xb00327c8, 0x98fb213f, 0xbf597fc7, 0xbeef0ee4, + 0xc6e00bf3, 0x3da88fc2, 0xd5a79147, 0x930aa725, + 0x06ca6351, 0xe003826f, 0x14292967, 0x0a0e6e70, + 0x27b70a85, 0x46d22ffc, 0x2e1b2138, 0x5c26c926, + 0x4d2c6dfc, 0x5ac42aed, 0x53380d13, 0x9d95b3df, + 0x650a7354, 0x8baf63de, 0x766a0abb, 0x3c77b2a8, + 0x81c2c92e, 0x47edaee6, 0x92722c85, 0x1482353b, + 0xa2bfe8a1, 0x4cf10364, 0xa81a664b, 0xbc423001, + 0xc24b8b70, 0xd0f89791, 0xc76c51a3, 0x0654be30, + 0xd192e819, 0xd6ef5218, 0xd6990624, 0x5565a910, + 0xf40e3585, 0x5771202a, 0x106aa070, 0x32bbd1b8, + 0x19a4c116, 0xb8d2d0c8, 0x1e376c08, 0x5141ab53, + 0x2748774c, 0xdf8eeb99, 0x34b0bcb5, 0xe19b48a8, + 0x391c0cb3, 0xc5c95a63, 0x4ed8aa4a, 0xe3418acb, + 0x5b9cca4f, 0x7763e373, 0x682e6ff3, 0xd6b2b8a3, + 0x748f82ee, 0x5defb2fc, 0x78a5636f, 0x43172f60, + 0x84c87814, 0xa1f0ab72, 0x8cc70208, 0x1a6439ec, + 0x90befffa, 0x23631e28, 0xa4506ceb, 0xde82bde9, + 0xbef9a3f7, 0xb2c67915, 0xc67178f2, 0xe372532b, + 0xca273ece, 0xea26619c, 0xd186b8c7, 0x21c0c207, + 0xeada7dd6, 0xcde0eb1e, 0xf57d4f7f, 0xee6ed178, + 0x06f067aa, 0x72176fba, 0x0a637dc5, 0xa2c898a6, + 0x113f9804, 0xbef90dae, 0x1b710b35, 0x131c471b, + 0x28db77f5, 0x23047d84, 0x32caab7b, 0x40c72493, + 0x3c9ebe0a, 0x15c9bebc, 0x431d67c4, 0x9c100d4c, + 0x4cc5d4be, 0xcb3e42b6, 0x597f299c, 0xfc657e2a, + 0x5fcb6fab, 0x3ad6faec, 0x6c44198c, 0x4a475817 +] + +var W = new Array(160) + +function Sha512 () { + this.init() + this._w = W + + Hash.call(this, 128, 112) +} + +inherits(Sha512, Hash) + +Sha512.prototype.init = function () { + this._ah = 0x6a09e667 + this._bh = 0xbb67ae85 + this._ch = 0x3c6ef372 + this._dh = 0xa54ff53a + this._eh = 0x510e527f + this._fh = 0x9b05688c + this._gh = 0x1f83d9ab + this._hh = 0x5be0cd19 + + this._al = 0xf3bcc908 + this._bl = 0x84caa73b + this._cl = 0xfe94f82b + this._dl = 0x5f1d36f1 + this._el = 0xade682d1 + this._fl = 0x2b3e6c1f + this._gl = 0xfb41bd6b + this._hl = 0x137e2179 + + return this +} + +function Ch (x, y, z) { + return z ^ (x & (y ^ z)) +} + +function maj (x, y, z) { + return (x & y) | (z & (x | y)) +} + +function sigma0 (x, xl) { + return (x >>> 28 | xl << 4) ^ (xl >>> 2 | x << 30) ^ (xl >>> 7 | x << 25) +} + +function sigma1 (x, xl) { + return (x >>> 14 | xl << 18) ^ (x >>> 18 | xl << 14) ^ (xl >>> 9 | x << 23) +} + +function Gamma0 (x, xl) { + return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7) +} + +function Gamma0l (x, xl) { + return (x >>> 1 | xl << 31) ^ (x >>> 8 | xl << 24) ^ (x >>> 7 | xl << 25) +} + +function Gamma1 (x, xl) { + return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6) +} + +function Gamma1l (x, xl) { + return (x >>> 19 | xl << 13) ^ (xl >>> 29 | x << 3) ^ (x >>> 6 | xl << 26) +} + +function getCarry (a, b) { + return (a >>> 0) < (b >>> 0) ? 1 : 0 +} + +Sha512.prototype._update = function (M) { + var W = this._w + + var ah = this._ah | 0 + var bh = this._bh | 0 + var ch = this._ch | 0 + var dh = this._dh | 0 + var eh = this._eh | 0 + var fh = this._fh | 0 + var gh = this._gh | 0 + var hh = this._hh | 0 + + var al = this._al | 0 + var bl = this._bl | 0 + var cl = this._cl | 0 + var dl = this._dl | 0 + var el = this._el | 0 + var fl = this._fl | 0 + var gl = this._gl | 0 + var hl = this._hl | 0 + + for (var i = 0; i < 32; i += 2) { + W[i] = M.readInt32BE(i * 4) + W[i + 1] = M.readInt32BE(i * 4 + 4) + } + for (; i < 160; i += 2) { + var xh = W[i - 15 * 2] + var xl = W[i - 15 * 2 + 1] + var gamma0 = Gamma0(xh, xl) + var gamma0l = Gamma0l(xl, xh) + + xh = W[i - 2 * 2] + xl = W[i - 2 * 2 + 1] + var gamma1 = Gamma1(xh, xl) + var gamma1l = Gamma1l(xl, xh) + + // W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16] + var Wi7h = W[i - 7 * 2] + var Wi7l = W[i - 7 * 2 + 1] + + var Wi16h = W[i - 16 * 2] + var Wi16l = W[i - 16 * 2 + 1] + + var Wil = (gamma0l + Wi7l) | 0 + var Wih = (gamma0 + Wi7h + getCarry(Wil, gamma0l)) | 0 + Wil = (Wil + gamma1l) | 0 + Wih = (Wih + gamma1 + getCarry(Wil, gamma1l)) | 0 + Wil = (Wil + Wi16l) | 0 + Wih = (Wih + Wi16h + getCarry(Wil, Wi16l)) | 0 + + W[i] = Wih + W[i + 1] = Wil + } + + for (var j = 0; j < 160; j += 2) { + Wih = W[j] + Wil = W[j + 1] + + var majh = maj(ah, bh, ch) + var majl = maj(al, bl, cl) + + var sigma0h = sigma0(ah, al) + var sigma0l = sigma0(al, ah) + var sigma1h = sigma1(eh, el) + var sigma1l = sigma1(el, eh) + + // t1 = h + sigma1 + ch + K[j] + W[j] + var Kih = K[j] + var Kil = K[j + 1] + + var chh = Ch(eh, fh, gh) + var chl = Ch(el, fl, gl) + + var t1l = (hl + sigma1l) | 0 + var t1h = (hh + sigma1h + getCarry(t1l, hl)) | 0 + t1l = (t1l + chl) | 0 + t1h = (t1h + chh + getCarry(t1l, chl)) | 0 + t1l = (t1l + Kil) | 0 + t1h = (t1h + Kih + getCarry(t1l, Kil)) | 0 + t1l = (t1l + Wil) | 0 + t1h = (t1h + Wih + getCarry(t1l, Wil)) | 0 + + // t2 = sigma0 + maj + var t2l = (sigma0l + majl) | 0 + var t2h = (sigma0h + majh + getCarry(t2l, sigma0l)) | 0 + + hh = gh + hl = gl + gh = fh + gl = fl + fh = eh + fl = el + el = (dl + t1l) | 0 + eh = (dh + t1h + getCarry(el, dl)) | 0 + dh = ch + dl = cl + ch = bh + cl = bl + bh = ah + bl = al + al = (t1l + t2l) | 0 + ah = (t1h + t2h + getCarry(al, t1l)) | 0 + } + + this._al = (this._al + al) | 0 + this._bl = (this._bl + bl) | 0 + this._cl = (this._cl + cl) | 0 + this._dl = (this._dl + dl) | 0 + this._el = (this._el + el) | 0 + this._fl = (this._fl + fl) | 0 + this._gl = (this._gl + gl) | 0 + this._hl = (this._hl + hl) | 0 + + this._ah = (this._ah + ah + getCarry(this._al, al)) | 0 + this._bh = (this._bh + bh + getCarry(this._bl, bl)) | 0 + this._ch = (this._ch + ch + getCarry(this._cl, cl)) | 0 + this._dh = (this._dh + dh + getCarry(this._dl, dl)) | 0 + this._eh = (this._eh + eh + getCarry(this._el, el)) | 0 + this._fh = (this._fh + fh + getCarry(this._fl, fl)) | 0 + this._gh = (this._gh + gh + getCarry(this._gl, gl)) | 0 + this._hh = (this._hh + hh + getCarry(this._hl, hl)) | 0 +} + +Sha512.prototype._hash = function () { + var H = Buffer.allocUnsafe(64) + + function writeInt64BE (h, l, offset) { + H.writeInt32BE(h, offset) + H.writeInt32BE(l, offset + 4) + } + + writeInt64BE(this._ah, this._al, 0) + writeInt64BE(this._bh, this._bl, 8) + writeInt64BE(this._ch, this._cl, 16) + writeInt64BE(this._dh, this._dl, 24) + writeInt64BE(this._eh, this._el, 32) + writeInt64BE(this._fh, this._fl, 40) + writeInt64BE(this._gh, this._gl, 48) + writeInt64BE(this._hh, this._hl, 56) + + return H +} + +module.exports = Sha512 + +},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/stream-browserify/index.js":[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +module.exports = Stream; + +var EE = require('events').EventEmitter; +var inherits = require('inherits'); + +inherits(Stream, EE); +Stream.Readable = require('readable-stream/readable.js'); +Stream.Writable = require('readable-stream/writable.js'); +Stream.Duplex = require('readable-stream/duplex.js'); +Stream.Transform = require('readable-stream/transform.js'); +Stream.PassThrough = require('readable-stream/passthrough.js'); + +// Backwards-compat with node 0.4.x +Stream.Stream = Stream; + + + +// old-style streams. Note that the pipe method (the only relevant +// part of this class) is overridden in the Readable class. + +function Stream() { + EE.call(this); +} + +Stream.prototype.pipe = function(dest, options) { + var source = this; + + function ondata(chunk) { + if (dest.writable) { + if (false === dest.write(chunk) && source.pause) { + source.pause(); + } + } + } + + source.on('data', ondata); + + function ondrain() { + if (source.readable && source.resume) { + source.resume(); + } + } + + dest.on('drain', ondrain); + + // If the 'end' option is not supplied, dest.end() will be called when + // source gets the 'end' or 'close' events. Only dest.end() once. + if (!dest._isStdio && (!options || options.end !== false)) { + source.on('end', onend); + source.on('close', onclose); + } + + var didOnEnd = false; + function onend() { + if (didOnEnd) return; + didOnEnd = true; + + dest.end(); + } + + + function onclose() { + if (didOnEnd) return; + didOnEnd = true; + + if (typeof dest.destroy === 'function') dest.destroy(); + } + + // don't leave dangling pipes when there are errors. + function onerror(er) { + cleanup(); + if (EE.listenerCount(this, 'error') === 0) { + throw er; // Unhandled stream error in pipe. + } + } + + source.on('error', onerror); + dest.on('error', onerror); + + // remove all the event listeners that were added. + function cleanup() { + source.removeListener('data', ondata); + dest.removeListener('drain', ondrain); + + source.removeListener('end', onend); + source.removeListener('close', onclose); + + source.removeListener('error', onerror); + dest.removeListener('error', onerror); + + source.removeListener('end', cleanup); + source.removeListener('close', cleanup); + + dest.removeListener('close', cleanup); + } + + source.on('end', cleanup); + source.on('close', cleanup); + + dest.on('close', cleanup); + + dest.emit('pipe', source); + + // Allow for unix-like usage: A.pipe(B).pipe(C) + return dest; +}; + +},{"events":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/events/events.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","readable-stream/duplex.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/duplex-browser.js","readable-stream/passthrough.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/passthrough.js","readable-stream/readable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/readable-browser.js","readable-stream/transform.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/transform.js","readable-stream/writable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/writable-browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/string_decoder/lib/string_decoder.js":[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +/**/ + +var Buffer = require('safe-buffer').Buffer; +/**/ + +var isEncoding = Buffer.isEncoding || function (encoding) { + encoding = '' + encoding; + switch (encoding && encoding.toLowerCase()) { + case 'hex':case 'utf8':case 'utf-8':case 'ascii':case 'binary':case 'base64':case 'ucs2':case 'ucs-2':case 'utf16le':case 'utf-16le':case 'raw': + return true; + default: + return false; + } +}; + +function _normalizeEncoding(enc) { + if (!enc) return 'utf8'; + var retried; + while (true) { + switch (enc) { + case 'utf8': + case 'utf-8': + return 'utf8'; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return 'utf16le'; + case 'latin1': + case 'binary': + return 'latin1'; + case 'base64': + case 'ascii': + case 'hex': + return enc; + default: + if (retried) return; // undefined + enc = ('' + enc).toLowerCase(); + retried = true; + } + } +}; + +// Do not cache `Buffer.isEncoding` when checking encoding names as some +// modules monkey-patch it to support additional encodings +function normalizeEncoding(enc) { + var nenc = _normalizeEncoding(enc); + if (typeof nenc !== 'string' && (Buffer.isEncoding === isEncoding || !isEncoding(enc))) throw new Error('Unknown encoding: ' + enc); + return nenc || enc; +} + +// StringDecoder provides an interface for efficiently splitting a series of +// buffers into a series of JS strings without breaking apart multi-byte +// characters. +exports.StringDecoder = StringDecoder; +function StringDecoder(encoding) { + this.encoding = normalizeEncoding(encoding); + var nb; + switch (this.encoding) { + case 'utf16le': + this.text = utf16Text; + this.end = utf16End; + nb = 4; + break; + case 'utf8': + this.fillLast = utf8FillLast; + nb = 4; + break; + case 'base64': + this.text = base64Text; + this.end = base64End; + nb = 3; + break; + default: + this.write = simpleWrite; + this.end = simpleEnd; + return; + } + this.lastNeed = 0; + this.lastTotal = 0; + this.lastChar = Buffer.allocUnsafe(nb); +} + +StringDecoder.prototype.write = function (buf) { + if (buf.length === 0) return ''; + var r; + var i; + if (this.lastNeed) { + r = this.fillLast(buf); + if (r === undefined) return ''; + i = this.lastNeed; + this.lastNeed = 0; + } else { + i = 0; + } + if (i < buf.length) return r ? r + this.text(buf, i) : this.text(buf, i); + return r || ''; +}; + +StringDecoder.prototype.end = utf8End; + +// Returns only complete characters in a Buffer +StringDecoder.prototype.text = utf8Text; + +// Attempts to complete a partial non-UTF-8 character using bytes from a Buffer +StringDecoder.prototype.fillLast = function (buf) { + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, this.lastTotal - this.lastNeed, 0, buf.length); + this.lastNeed -= buf.length; +}; + +// Checks the type of a UTF-8 byte, whether it's ASCII, a leading byte, or a +// continuation byte. If an invalid byte is detected, -2 is returned. +function utf8CheckByte(byte) { + if (byte <= 0x7F) return 0;else if (byte >> 5 === 0x06) return 2;else if (byte >> 4 === 0x0E) return 3;else if (byte >> 3 === 0x1E) return 4; + return byte >> 6 === 0x02 ? -1 : -2; +} + +// Checks at most 3 bytes at the end of a Buffer in order to detect an +// incomplete multi-byte UTF-8 character. The total number of bytes (2, 3, or 4) +// needed to complete the UTF-8 character (if applicable) are returned. +function utf8CheckIncomplete(self, buf, i) { + var j = buf.length - 1; + if (j < i) return 0; + var nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 1; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) self.lastNeed = nb - 2; + return nb; + } + if (--j < i || nb === -2) return 0; + nb = utf8CheckByte(buf[j]); + if (nb >= 0) { + if (nb > 0) { + if (nb === 2) nb = 0;else self.lastNeed = nb - 3; + } + return nb; + } + return 0; +} + +// Validates as many continuation bytes for a multi-byte UTF-8 character as +// needed or are available. If we see a non-continuation byte where we expect +// one, we "replace" the validated continuation bytes we've seen so far with +// a single UTF-8 replacement character ('\ufffd'), to match v8's UTF-8 decoding +// behavior. The continuation byte check is included three times in the case +// where all of the continuation bytes for a character exist in the same buffer. +// It is also done this way as a slight performance increase instead of using a +// loop. +function utf8CheckExtraBytes(self, buf, p) { + if ((buf[0] & 0xC0) !== 0x80) { + self.lastNeed = 0; + return '\ufffd'; + } + if (self.lastNeed > 1 && buf.length > 1) { + if ((buf[1] & 0xC0) !== 0x80) { + self.lastNeed = 1; + return '\ufffd'; + } + if (self.lastNeed > 2 && buf.length > 2) { + if ((buf[2] & 0xC0) !== 0x80) { + self.lastNeed = 2; + return '\ufffd'; + } + } + } +} + +// Attempts to complete a multi-byte UTF-8 character using bytes from a Buffer. +function utf8FillLast(buf) { + var p = this.lastTotal - this.lastNeed; + var r = utf8CheckExtraBytes(this, buf, p); + if (r !== undefined) return r; + if (this.lastNeed <= buf.length) { + buf.copy(this.lastChar, p, 0, this.lastNeed); + return this.lastChar.toString(this.encoding, 0, this.lastTotal); + } + buf.copy(this.lastChar, p, 0, buf.length); + this.lastNeed -= buf.length; +} + +// Returns all complete UTF-8 characters in a Buffer. If the Buffer ended on a +// partial character, the character's bytes are buffered until the required +// number of bytes are available. +function utf8Text(buf, i) { + var total = utf8CheckIncomplete(this, buf, i); + if (!this.lastNeed) return buf.toString('utf8', i); + this.lastTotal = total; + var end = buf.length - (total - this.lastNeed); + buf.copy(this.lastChar, 0, end); + return buf.toString('utf8', i, end); +} + +// For UTF-8, a replacement character is added when ending on a partial +// character. +function utf8End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + '\ufffd'; + return r; +} + +// UTF-16LE typically needs two bytes per character, but even if we have an even +// number of bytes available, we need to check if we end on a leading/high +// surrogate. In that case, we need to wait for the next two bytes in order to +// decode the last character properly. +function utf16Text(buf, i) { + if ((buf.length - i) % 2 === 0) { + var r = buf.toString('utf16le', i); + if (r) { + var c = r.charCodeAt(r.length - 1); + if (c >= 0xD800 && c <= 0xDBFF) { + this.lastNeed = 2; + this.lastTotal = 4; + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + return r.slice(0, -1); + } + } + return r; + } + this.lastNeed = 1; + this.lastTotal = 2; + this.lastChar[0] = buf[buf.length - 1]; + return buf.toString('utf16le', i, buf.length - 1); +} + +// For UTF-16LE we do not explicitly append special replacement characters if we +// end on a partial character, we simply let v8 handle that. +function utf16End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) { + var end = this.lastTotal - this.lastNeed; + return r + this.lastChar.toString('utf16le', 0, end); + } + return r; +} + +function base64Text(buf, i) { + var n = (buf.length - i) % 3; + if (n === 0) return buf.toString('base64', i); + this.lastNeed = 3 - n; + this.lastTotal = 3; + if (n === 1) { + this.lastChar[0] = buf[buf.length - 1]; + } else { + this.lastChar[0] = buf[buf.length - 2]; + this.lastChar[1] = buf[buf.length - 1]; + } + return buf.toString('base64', i, buf.length - n); +} + +function base64End(buf) { + var r = buf && buf.length ? this.write(buf) : ''; + if (this.lastNeed) return r + this.lastChar.toString('base64', 0, 3 - this.lastNeed); + return r; +} + +// Pass bytes on through for single-byte encodings (e.g. ascii, latin1, hex) +function simpleWrite(buf) { + return buf.toString(this.encoding); +} + +function simpleEnd(buf) { + return buf && buf.length ? this.write(buf) : ''; +} +},{"safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/timers-browserify/main.js":[function(require,module,exports){ +(function (setImmediate,clearImmediate){ +var nextTick = require('process/browser.js').nextTick; +var apply = Function.prototype.apply; +var slice = Array.prototype.slice; +var immediateIds = {}; +var nextImmediateId = 0; + +// DOM APIs, for completeness + +exports.setTimeout = function() { + return new Timeout(apply.call(setTimeout, window, arguments), clearTimeout); +}; +exports.setInterval = function() { + return new Timeout(apply.call(setInterval, window, arguments), clearInterval); +}; +exports.clearTimeout = +exports.clearInterval = function(timeout) { timeout.close(); }; + +function Timeout(id, clearFn) { + this._id = id; + this._clearFn = clearFn; +} +Timeout.prototype.unref = Timeout.prototype.ref = function() {}; +Timeout.prototype.close = function() { + this._clearFn.call(window, this._id); +}; + +// Does not start the time, just sets up the members needed. +exports.enroll = function(item, msecs) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = msecs; +}; + +exports.unenroll = function(item) { + clearTimeout(item._idleTimeoutId); + item._idleTimeout = -1; +}; + +exports._unrefActive = exports.active = function(item) { + clearTimeout(item._idleTimeoutId); + + var msecs = item._idleTimeout; + if (msecs >= 0) { + item._idleTimeoutId = setTimeout(function onTimeout() { + if (item._onTimeout) + item._onTimeout(); + }, msecs); + } +}; + +// That's not how node.js implements it but the exposed api is the same. +exports.setImmediate = typeof setImmediate === "function" ? setImmediate : function(fn) { + var id = nextImmediateId++; + var args = arguments.length < 2 ? false : slice.call(arguments, 1); + + immediateIds[id] = true; + + nextTick(function onNextTick() { + if (immediateIds[id]) { + // fn.call() is faster so we optimize for the common use-case + // @see http://jsperf.com/call-apply-segu + if (args) { + fn.apply(null, args); + } else { + fn.call(null); + } + // Prevent ids from leaking + exports.clearImmediate(id); + } + }); + + return id; +}; + +exports.clearImmediate = typeof clearImmediate === "function" ? clearImmediate : function(id) { + delete immediateIds[id]; +}; +}).call(this,require("timers").setImmediate,require("timers").clearImmediate) + +},{"process/browser.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js","timers":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/timers-browserify/main.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/util-deprecate/browser.js":[function(require,module,exports){ +(function (global){ + +/** + * Module exports. + */ + +module.exports = deprecate; + +/** + * Mark that a method should not be used. + * Returns a modified function which warns once by default. + * + * If `localStorage.noDeprecation = true` is set, then it is a no-op. + * + * If `localStorage.throwDeprecation = true` is set, then deprecated functions + * will throw an Error when invoked. + * + * If `localStorage.traceDeprecation = true` is set, then deprecated functions + * will invoke `console.trace()` instead of `console.error()`. + * + * @param {Function} fn - the function to deprecate + * @param {String} msg - the string to print to the console when `fn` is invoked + * @returns {Function} a new "deprecated" version of `fn` + * @api public + */ + +function deprecate (fn, msg) { + if (config('noDeprecation')) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (config('throwDeprecation')) { + throw new Error(msg); + } else if (config('traceDeprecation')) { + console.trace(msg); + } else { + console.warn(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +} + +/** + * Checks `localStorage` for boolean values for the given `name`. + * + * @param {String} name + * @returns {Boolean} + * @api private + */ + +function config (name) { + // accessing global.localStorage can trigger a DOMException in sandboxed iframes + try { + if (!global.localStorage) return false; + } catch (_) { + return false; + } + var val = global.localStorage[name]; + if (null == val) return false; + return String(val).toLowerCase() === 'true'; +} + +}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/util/node_modules/inherits/inherits_browser.js":[function(require,module,exports){ +arguments[4]["/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js"][0].apply(exports,arguments) +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/util/support/isBufferBrowser.js":[function(require,module,exports){ +module.exports = function isBuffer(arg) { + return arg && typeof arg === 'object' + && typeof arg.copy === 'function' + && typeof arg.fill === 'function' + && typeof arg.readUInt8 === 'function'; +} +},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/util/util.js":[function(require,module,exports){ +(function (process,global){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + + +// Mark that a method should not be used. +// Returns a modified function which warns once by default. +// If --no-deprecation is set, then it is a no-op. +exports.deprecate = function(fn, msg) { + // Allow for deprecating things in the process of starting up. + if (isUndefined(global.process)) { + return function() { + return exports.deprecate(fn, msg).apply(this, arguments); + }; + } + + if (process.noDeprecation === true) { + return fn; + } + + var warned = false; + function deprecated() { + if (!warned) { + if (process.throwDeprecation) { + throw new Error(msg); + } else if (process.traceDeprecation) { + console.trace(msg); + } else { + console.error(msg); + } + warned = true; + } + return fn.apply(this, arguments); + } + + return deprecated; +}; + + +var debugs = {}; +var debugEnviron; +exports.debuglog = function(set) { + if (isUndefined(debugEnviron)) + debugEnviron = process.env.NODE_DEBUG || ''; + set = set.toUpperCase(); + if (!debugs[set]) { + if (new RegExp('\\b' + set + '\\b', 'i').test(debugEnviron)) { + var pid = process.pid; + debugs[set] = function() { + var msg = exports.format.apply(exports, arguments); + console.error('%s %d: %s', set, pid, msg); + }; + } else { + debugs[set] = function() {}; + } + } + return debugs[set]; +}; + + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + array.forEach(function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes, ctx); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = Object.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = Object.getOwnPropertyNames(value); + } + + // IE doesn't make error fields non-enumerable + // http://msdn.microsoft.com/en-us/library/ie/dww52sbt(v=vs.94).aspx + if (isError(value) + && (keys.indexOf('message') >= 0 || keys.indexOf('description') >= 0)) { + return formatError(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + keys.forEach(function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = Object.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (ctx.seen.indexOf(desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = output.reduce(function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return Array.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg !== null; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && + (objectToString(e) === '[object Error]' || e instanceof Error); +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +exports.isBuffer = require('./support/isBuffer'); + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = require('inherits'); + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = Object.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +}).call(this,require('_process'),typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) + +},{"./support/isBuffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/util/support/isBufferBrowser.js","_process":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process/browser.js","inherits":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/util/node_modules/inherits/inherits_browser.js"}]},{},["/Users/mseaward/Documents/code/peerplaysjs-lib/dist/browser.js"])("/Users/mseaward/Documents/code/peerplaysjs-lib/dist/browser.js") +}); + +//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIm5vZGVfbW9kdWxlcy9icm93c2VyLXBhY2svX3ByZWx1ZGUuanMiLCJkaXN0L2Jyb3dzZXIuanMiLCJkaXN0L2NoYWluL3NyYy9BY2NvdW50TG9naW4uanMiLCJkaXN0L2NoYWluL3NyYy9DaGFpblR5cGVzLmpzIiwiZGlzdC9jaGFpbi9zcmMvT2JqZWN0SWQuanMiLCJkaXN0L2NoYWluL3NyYy9UcmFuc2FjdGlvbkJ1aWxkZXIuanMiLCJkaXN0L2NoYWluL3NyYy9zdGF0ZS5qcyIsImRpc3QvZWNjL2luZGV4LmpzIiwiZGlzdC9lY2Mvc3JjL0JyYWluS2V5LmpzIiwiZGlzdC9lY2Mvc3JjL0tleVV0aWxzLmpzIiwiZGlzdC9lY2Mvc3JjL1ByaXZhdGVLZXkuanMiLCJkaXN0L2VjYy9zcmMvUHVibGljS2V5LmpzIiwiZGlzdC9lY2Mvc3JjL2FkZHJlc3MuanMiLCJkaXN0L2VjYy9zcmMvYWVzLmpzIiwiZGlzdC9lY2Mvc3JjL2VjZHNhLmpzIiwiZGlzdC9lY2Mvc3JjL2Vjc2lnbmF0dXJlLmpzIiwiZGlzdC9lY2Mvc3JjL2VuZm9yY2VfdHlwZXMuanMiLCJkaXN0L2VjYy9zcmMvaGFzaC5qcyIsImRpc3QvZWNjL3NyYy9zaWduYXR1cmUuanMiLCJkaXN0L3NlcmlhbGl6ZXIvaW5kZXguanMiLCJkaXN0L3NlcmlhbGl6ZXIvc3JjL0Zhc3RQYXJzZXIuanMiLCJkaXN0L3NlcmlhbGl6ZXIvc3JjL1NlcmlhbGl6ZXJWYWxpZGF0aW9uLmpzIiwiZGlzdC9zZXJpYWxpemVyL3NyYy9lcnJvcl93aXRoX2NhdXNlLmpzIiwiZGlzdC9zZXJpYWxpemVyL3NyYy9vcGVyYXRpb25zLmpzIiwiZGlzdC9zZXJpYWxpemVyL3NyYy9zZXJpYWxpemVyLmpzIiwiZGlzdC9zZXJpYWxpemVyL3NyYy90ZW1wbGF0ZS5qcyIsImRpc3Qvc2VyaWFsaXplci9zcmMvdHlwZXMuanMiLCJub2RlX21vZHVsZXMvYXNzZXJ0L2Fzc2VydC5qcyIsIm5vZGVfbW9kdWxlcy9iYXNlLXgvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYmFzZTY0LWpzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2JpZ2kvbGliL2JpZ2kuanMiLCJub2RlX21vZHVsZXMvYmlnaS9saWIvY29udmVydC5qcyIsIm5vZGVfbW9kdWxlcy9iaWdpL2xpYi9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9iaWdpL3BhY2thZ2UuanNvbiIsIm5vZGVfbW9kdWxlcy9icm93c2VyLXJlc29sdmUvZW1wdHkuanMiLCJub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnVmZmVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2Jyb3dzZXJpZnkvbm9kZV9tb2R1bGVzL3N0cmluZ19kZWNvZGVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2JzNTgvaW5kZXguanMiLCJub2RlX21vZHVsZXMvYnl0ZWJ1ZmZlci9kaXN0L2J5dGVidWZmZXIuanMiLCJub2RlX21vZHVsZXMvY2lwaGVyLWJhc2UvaW5kZXguanMiLCJub2RlX21vZHVsZXMvY29yZS11dGlsLWlzL2xpYi91dGlsLmpzIiwibm9kZV9tb2R1bGVzL2NyZWF0ZS1oYXNoL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvY3JlYXRlLWhhc2gvbWQ1LmpzIiwibm9kZV9tb2R1bGVzL2NyZWF0ZS1obWFjL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvY3JlYXRlLWhtYWMvbGVnYWN5LmpzIiwibm9kZV9tb2R1bGVzL2NyeXB0by1qcy9hZXMuanMiLCJub2RlX21vZHVsZXMvY3J5cHRvLWpzL2NpcGhlci1jb3JlLmpzIiwibm9kZV9tb2R1bGVzL2NyeXB0by1qcy9jb3JlLmpzIiwibm9kZV9tb2R1bGVzL2NyeXB0by1qcy9lbmMtYmFzZTY0LmpzIiwibm9kZV9tb2R1bGVzL2NyeXB0by1qcy9lbmMtaGV4LmpzIiwibm9kZV9tb2R1bGVzL2NyeXB0by1qcy9ldnBrZGYuanMiLCJub2RlX21vZHVsZXMvY3J5cHRvLWpzL2htYWMuanMiLCJub2RlX21vZHVsZXMvY3J5cHRvLWpzL21kNS5qcyIsIm5vZGVfbW9kdWxlcy9jcnlwdG8tanMvc2hhMS5qcyIsIm5vZGVfbW9kdWxlcy9kZWVwLWVxdWFsL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2RlZXAtZXF1YWwvbGliL2lzX2FyZ3VtZW50cy5qcyIsIm5vZGVfbW9kdWxlcy9kZWVwLWVxdWFsL2xpYi9rZXlzLmpzIiwibm9kZV9tb2R1bGVzL2VjdXJ2ZS9saWIvY3VydmUuanMiLCJub2RlX21vZHVsZXMvZWN1cnZlL2xpYi9jdXJ2ZXMuanNvbiIsIm5vZGVfbW9kdWxlcy9lY3VydmUvbGliL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2VjdXJ2ZS9saWIvbmFtZXMuanMiLCJub2RlX21vZHVsZXMvZWN1cnZlL2xpYi9wb2ludC5qcyIsIm5vZGVfbW9kdWxlcy9ldmVudHMvZXZlbnRzLmpzIiwibm9kZV9tb2R1bGVzL2hhc2gtYmFzZS9pbmRleC5qcyIsIm5vZGVfbW9kdWxlcy9pZWVlNzU0L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2luaGVyaXRzL2luaGVyaXRzX2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvaXMtYnVmZmVyL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL2lzYXJyYXkvaW5kZXguanMiLCJub2RlX21vZHVsZXMvbG9uZy9kaXN0L2xvbmcuanMiLCJub2RlX21vZHVsZXMvbWQ1LmpzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3BlZXJwbGF5c2pzLXdzL2Rpc3QvaW5kZXguanMiLCJub2RlX21vZHVsZXMvcGVlcnBsYXlzanMtd3MvZGlzdC9zcmMvQXBpSW5zdGFuY2VzLmpzIiwibm9kZV9tb2R1bGVzL3BlZXJwbGF5c2pzLXdzL2Rpc3Qvc3JjL0NoYWluQ29uZmlnLmpzIiwibm9kZV9tb2R1bGVzL3BlZXJwbGF5c2pzLXdzL2Rpc3Qvc3JjL0NoYWluV2ViU29ja2V0LmpzIiwibm9kZV9tb2R1bGVzL3BlZXJwbGF5c2pzLXdzL2Rpc3Qvc3JjL0Nvbm5lY3Rpb25NYW5hZ2VyLmpzIiwibm9kZV9tb2R1bGVzL3BlZXJwbGF5c2pzLXdzL2Rpc3Qvc3JjL0dyYXBoZW5lQXBpLmpzIiwibm9kZV9tb2R1bGVzL3Byb2Nlc3MtbmV4dGljay1hcmdzL2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3Byb2Nlc3MvYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9yZWFkYWJsZS1zdHJlYW0vZHVwbGV4LWJyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvcmVhZGFibGUtc3RyZWFtL2xpYi9fc3RyZWFtX2R1cGxleC5qcyIsIm5vZGVfbW9kdWxlcy9yZWFkYWJsZS1zdHJlYW0vbGliL19zdHJlYW1fcGFzc3Rocm91Z2guanMiLCJub2RlX21vZHVsZXMvcmVhZGFibGUtc3RyZWFtL2xpYi9fc3RyZWFtX3JlYWRhYmxlLmpzIiwibm9kZV9tb2R1bGVzL3JlYWRhYmxlLXN0cmVhbS9saWIvX3N0cmVhbV90cmFuc2Zvcm0uanMiLCJub2RlX21vZHVsZXMvcmVhZGFibGUtc3RyZWFtL2xpYi9fc3RyZWFtX3dyaXRhYmxlLmpzIiwibm9kZV9tb2R1bGVzL3JlYWRhYmxlLXN0cmVhbS9saWIvaW50ZXJuYWwvc3RyZWFtcy9CdWZmZXJMaXN0LmpzIiwibm9kZV9tb2R1bGVzL3JlYWRhYmxlLXN0cmVhbS9saWIvaW50ZXJuYWwvc3RyZWFtcy9kZXN0cm95LmpzIiwibm9kZV9tb2R1bGVzL3JlYWRhYmxlLXN0cmVhbS9saWIvaW50ZXJuYWwvc3RyZWFtcy9zdHJlYW0tYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9yZWFkYWJsZS1zdHJlYW0vcGFzc3Rocm91Z2guanMiLCJub2RlX21vZHVsZXMvcmVhZGFibGUtc3RyZWFtL3JlYWRhYmxlLWJyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvcmVhZGFibGUtc3RyZWFtL3RyYW5zZm9ybS5qcyIsIm5vZGVfbW9kdWxlcy9yZWFkYWJsZS1zdHJlYW0vd3JpdGFibGUtYnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy9yaXBlbWQxNjAvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc2FmZS1idWZmZXIvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc2VjdXJlLXJhbmRvbS9saWIvc2VjdXJlLXJhbmRvbS5qcyIsIm5vZGVfbW9kdWxlcy9zaGEuanMvaGFzaC5qcyIsIm5vZGVfbW9kdWxlcy9zaGEuanMvaW5kZXguanMiLCJub2RlX21vZHVsZXMvc2hhLmpzL3NoYS5qcyIsIm5vZGVfbW9kdWxlcy9zaGEuanMvc2hhMS5qcyIsIm5vZGVfbW9kdWxlcy9zaGEuanMvc2hhMjI0LmpzIiwibm9kZV9tb2R1bGVzL3NoYS5qcy9zaGEyNTYuanMiLCJub2RlX21vZHVsZXMvc2hhLmpzL3NoYTM4NC5qcyIsIm5vZGVfbW9kdWxlcy9zaGEuanMvc2hhNTEyLmpzIiwibm9kZV9tb2R1bGVzL3N0cmVhbS1icm93c2VyaWZ5L2luZGV4LmpzIiwibm9kZV9tb2R1bGVzL3N0cmluZ19kZWNvZGVyL2xpYi9zdHJpbmdfZGVjb2Rlci5qcyIsIm5vZGVfbW9kdWxlcy90aW1lcnMtYnJvd3NlcmlmeS9tYWluLmpzIiwibm9kZV9tb2R1bGVzL3V0aWwtZGVwcmVjYXRlL2Jyb3dzZXIuanMiLCJub2RlX21vZHVsZXMvdXRpbC9zdXBwb3J0L2lzQnVmZmVyQnJvd3Nlci5qcyIsIm5vZGVfbW9kdWxlcy91dGlsL3V0aWwuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDdEVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzlrQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbEJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ1JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ3pNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDcE5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDM09BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDOUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDblRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUMxTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUMvSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNoREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUMxTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3JCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN6RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNwc0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzlNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDLy9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDMWVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3IrQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzNGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7OztBQ0FBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUM3dkRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbHFIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzNHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdk9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMTJCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2dkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDakVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDVkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFBBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5U0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9GQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNwRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUN6ckNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUNqSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFMQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2xlQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDakNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzVDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3hMQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbElBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzlDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDMS9CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDck5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzlxQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDekVBO0FBQ0E7O0FDREE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ1BBO0FBQ0E7O0FDREE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25LQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQzlEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQzlFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDZkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdklBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3pEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDcFFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDL0hBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQ3ZTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUMzRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsImZpbGUiOiJnZW5lcmF0ZWQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uKCl7ZnVuY3Rpb24gcihlLG4sdCl7ZnVuY3Rpb24gbyhpLGYpe2lmKCFuW2ldKXtpZighZVtpXSl7dmFyIGM9XCJmdW5jdGlvblwiPT10eXBlb2YgcmVxdWlyZSYmcmVxdWlyZTtpZighZiYmYylyZXR1cm4gYyhpLCEwKTtpZih1KXJldHVybiB1KGksITApO3ZhciBhPW5ldyBFcnJvcihcIkNhbm5vdCBmaW5kIG1vZHVsZSAnXCIraStcIidcIik7dGhyb3cgYS5jb2RlPVwiTU9EVUxFX05PVF9GT1VORFwiLGF9dmFyIHA9bltpXT17ZXhwb3J0czp7fX07ZVtpXVswXS5jYWxsKHAuZXhwb3J0cyxmdW5jdGlvbihyKXt2YXIgbj1lW2ldWzFdW3JdO3JldHVybiBvKG58fHIpfSxwLHAuZXhwb3J0cyxyLGUsbix0KX1yZXR1cm4gbltpXS5leHBvcnRzfWZvcih2YXIgdT1cImZ1bmN0aW9uXCI9PXR5cGVvZiByZXF1aXJlJiZyZXF1aXJlLGk9MDtpPHQubGVuZ3RoO2krKylvKHRbaV0pO3JldHVybiBvfXJldHVybiByfSkoKSIsIlwidXNlIHN0cmljdFwiO1xuXG5tb2R1bGUuZXhwb3J0cyA9IHtcbiAgICBQcml2YXRlS2V5OiByZXF1aXJlKFwiLi9lY2Mvc3JjL1ByaXZhdGVLZXlcIiksXG4gICAgUHVibGljS2V5OiByZXF1aXJlKFwiLi9lY2Mvc3JjL1B1YmxpY0tleVwiKSxcbiAgICBTaWduYXR1cmU6IHJlcXVpcmUoXCIuL2VjYy9zcmMvc2lnbmF0dXJlXCIpLFxuICAgIGtleTogcmVxdWlyZShcIi4vZWNjL3NyYy9LZXlVdGlsc1wiKSxcbiAgICBUcmFuc2FjdGlvbkJ1aWxkZXI6IHJlcXVpcmUoXCIuL2NoYWluL3NyYy9UcmFuc2FjdGlvbkJ1aWxkZXJcIiksXG4gICAgTG9naW46IHJlcXVpcmUoXCIuL2NoYWluL3NyYy9BY2NvdW50TG9naW5cIiksXG4gICAgZ3JhcGhlbmVXUzogcmVxdWlyZShcInBlZXJwbGF5c2pzLXdzXCIpXG59OyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG52YXIgUHJpdmF0ZUtleSA9IHJlcXVpcmUoXCIuLi8uLi9lY2Mvc3JjL1ByaXZhdGVLZXlcIik7XG52YXIga2V5ID0gcmVxdWlyZShcIi4uLy4uL2VjYy9zcmMvS2V5VXRpbHNcIik7XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoXCIuL3N0YXRlXCIpLFxuICAgIGdldCA9IF9yZXF1aXJlLmdldCxcbiAgICBzZXQgPSBfcmVxdWlyZS5zZXQ7XG5cbnZhciBfa2V5Q2FjaGVQcml2ID0ge307XG52YXIgX2tleUNhY2hlUHViID0ge307XG5cbnZhciBBY2NvdW50TG9naW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQWNjb3VudExvZ2luKCkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQWNjb3VudExvZ2luKTtcblxuICAgICAgICB2YXIgc3RhdGUgPSB7IGxvZ2dlZEluOiBmYWxzZSwgcm9sZXM6IFtcImFjdGl2ZVwiLCBcIm93bmVyXCIsIFwibWVtb1wiXSB9O1xuICAgICAgICB0aGlzLmdldCA9IGdldChzdGF0ZSk7XG4gICAgICAgIHRoaXMuc2V0ID0gc2V0KHN0YXRlKTtcblxuICAgICAgICB0aGlzLnN1YnMgPSB7fTtcbiAgICB9XG5cbiAgICBfY3JlYXRlQ2xhc3MoQWNjb3VudExvZ2luLCBbe1xuICAgICAgICBrZXk6IFwiYWRkU3Vic2NyaXB0aW9uXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBhZGRTdWJzY3JpcHRpb24oY2IpIHtcbiAgICAgICAgICAgIHRoaXMuc3Vic1tjYl0gPSBjYjtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcInNldFJvbGVzXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzZXRSb2xlcyhyb2xlcykge1xuICAgICAgICAgICAgdGhpcy5zZXQoXCJyb2xlc1wiLCByb2xlcyk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJnZW5lcmF0ZUtleXNcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdlbmVyYXRlS2V5cyhhY2NvdW50TmFtZSwgcGFzc3dvcmQsIHJvbGVzLCBwcmVmaXgpIHtcbiAgICAgICAgICAgIHZhciBzdGFydCA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpO1xuICAgICAgICAgICAgaWYgKCFhY2NvdW50TmFtZSB8fCAhcGFzc3dvcmQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJBY2NvdW50IG5hbWUgb3IgcGFzc3dvcmQgcmVxdWlyZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocGFzc3dvcmQubGVuZ3RoIDwgMTIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJQYXNzd29yZCBtdXN0IGhhdmUgYXQgbGVhc3QgMTIgY2hhcmFjdGVyc1wiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIHByaXZLZXlzID0ge307XG4gICAgICAgICAgICB2YXIgcHViS2V5cyA9IHt9O1xuXG4gICAgICAgICAgICAocm9sZXMgfHwgdGhpcy5nZXQoXCJyb2xlc1wiKSkuZm9yRWFjaChmdW5jdGlvbiAocm9sZSkge1xuICAgICAgICAgICAgICAgIHZhciBzZWVkID0gYWNjb3VudE5hbWUgKyByb2xlICsgcGFzc3dvcmQ7XG4gICAgICAgICAgICAgICAgdmFyIHBrZXkgPSBfa2V5Q2FjaGVQcml2W3NlZWRdID8gX2tleUNhY2hlUHJpdltzZWVkXSA6IFByaXZhdGVLZXkuZnJvbVNlZWQoa2V5Lm5vcm1hbGl6ZV9icmFpbktleShzZWVkKSk7XG4gICAgICAgICAgICAgICAgX2tleUNhY2hlUHJpdltzZWVkXSA9IHBrZXk7XG5cbiAgICAgICAgICAgICAgICBwcml2S2V5c1tyb2xlXSA9IHBrZXk7XG4gICAgICAgICAgICAgICAgcHViS2V5c1tyb2xlXSA9IF9rZXlDYWNoZVB1YltzZWVkXSA/IF9rZXlDYWNoZVB1YltzZWVkXSA6IHBrZXkudG9QdWJsaWNLZXkoKS50b1N0cmluZyhwcmVmaXgpO1xuXG4gICAgICAgICAgICAgICAgX2tleUNhY2hlUHViW3NlZWRdID0gcHViS2V5c1tyb2xlXTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICByZXR1cm4geyBwcml2S2V5czogcHJpdktleXMsIHB1YktleXM6IHB1YktleXMgfTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImNoZWNrS2V5c1wiLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gY2hlY2tLZXlzKF9yZWYpIHtcbiAgICAgICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBhY2NvdW50TmFtZSA9IF9yZWYuYWNjb3VudE5hbWUsXG4gICAgICAgICAgICAgICAgcGFzc3dvcmQgPSBfcmVmLnBhc3N3b3JkLFxuICAgICAgICAgICAgICAgIGF1dGhzID0gX3JlZi5hdXRocztcblxuICAgICAgICAgICAgaWYgKCFhY2NvdW50TmFtZSB8fCAhcGFzc3dvcmQgfHwgIWF1dGhzKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiY2hlY2tLZXlzOiBNaXNzaW5nIGlucHV0c1wiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBoYXNLZXkgPSBmYWxzZTtcblxuICAgICAgICAgICAgdmFyIF9sb29wID0gZnVuY3Rpb24gX2xvb3Aocm9sZSkge1xuICAgICAgICAgICAgICAgIHZhciBfZ2VuZXJhdGVLZXlzID0gX3RoaXMuZ2VuZXJhdGVLZXlzKGFjY291bnROYW1lLCBwYXNzd29yZCwgW3JvbGVdKSxcbiAgICAgICAgICAgICAgICAgICAgcHJpdktleXMgPSBfZ2VuZXJhdGVLZXlzLnByaXZLZXlzLFxuICAgICAgICAgICAgICAgICAgICBwdWJLZXlzID0gX2dlbmVyYXRlS2V5cy5wdWJLZXlzO1xuXG4gICAgICAgICAgICAgICAgYXV0aHNbcm9sZV0uZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChrZXlbMF0gPT09IHB1YktleXNbcm9sZV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc0tleSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXQocm9sZSwgeyBwcml2OiBwcml2S2V5c1tyb2xlXSwgcHViOiBwdWJLZXlzW3JvbGVdIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBmb3IgKHZhciByb2xlIGluIGF1dGhzKSB7XG4gICAgICAgICAgICAgICAgX2xvb3Aocm9sZSk7XG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBpZiAoaGFzS2V5KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXQoXCJuYW1lXCIsIGFjY291bnROYW1lKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5zZXQoXCJsb2dnZWRJblwiLCBoYXNLZXkpO1xuXG4gICAgICAgICAgICByZXR1cm4gaGFzS2V5O1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6IFwic2lnblRyYW5zYWN0aW9uXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzaWduVHJhbnNhY3Rpb24odHIpIHtcbiAgICAgICAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICAgICAgICB2YXIgbXlLZXlzID0ge307XG4gICAgICAgICAgICB2YXIgaGFzS2V5ID0gZmFsc2U7XG5cbiAgICAgICAgICAgIHRoaXMuZ2V0KFwicm9sZXNcIikuZm9yRWFjaChmdW5jdGlvbiAocm9sZSkge1xuICAgICAgICAgICAgICAgIHZhciBteUtleSA9IF90aGlzMi5nZXQocm9sZSk7XG4gICAgICAgICAgICAgICAgaWYgKG15S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc0tleSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiYWRkaW5nIHNpZ25lcjpcIiwgbXlLZXkucHViKTtcbiAgICAgICAgICAgICAgICAgICAgdHIuYWRkX3NpZ25lcihteUtleS5wcml2LCBteUtleS5wdWIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICBpZiAoIWhhc0tleSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIllvdSBkbyBub3QgaGF2ZSBhbnkgcHJpdmF0ZSBrZXlzIHRvIHNpZ24gdGhpcyB0cmFuc2FjdGlvblwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1dKTtcblxuICAgIHJldHVybiBBY2NvdW50TG9naW47XG59KCk7XG5cbnZhciBhY2NvdW50TG9naW4gPSBuZXcgQWNjb3VudExvZ2luKCk7XG5cbm1vZHVsZS5leHBvcnRzID0gYWNjb3VudExvZ2luOyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgQ2hhaW5UeXBlcyA9IHt9O1xuXG5DaGFpblR5cGVzLnJlc2VydmVkX3NwYWNlcyA9IHtcbiAgcmVsYXRpdmVfcHJvdG9jb2xfaWRzOiAwLFxuICBwcm90b2NvbF9pZHM6IDEsXG4gIGltcGxlbWVudGF0aW9uX2lkczogMlxufTtcblxuQ2hhaW5UeXBlcy5vYmplY3RfdHlwZSA9IHtcbiAgXCJudWxsXCI6IDAsXG4gIGJhc2U6IDEsXG4gIGFjY291bnQ6IDIsXG4gIGFzc2V0OiAzLFxuICBmb3JjZV9zZXR0bGVtZW50OiA0LFxuICBjb21taXR0ZWVfbWVtYmVyOiA1LFxuICB3aXRuZXNzOiA2LFxuICBsaW1pdF9vcmRlcjogNyxcbiAgY2FsbF9vcmRlcjogOCxcbiAgY3VzdG9tOiA5LFxuICBwcm9wb3NhbDogMTAsXG4gIG9wZXJhdGlvbl9oaXN0b3J5OiAxMSxcbiAgd2l0aGRyYXdfcGVybWlzc2lvbjogMTIsXG4gIHZlc3RpbmdfYmFsYW5jZTogMTMsXG4gIHdvcmtlcjogMTQsXG4gIGJhbGFuY2U6IDE1LFxuICB0b3VybmFtZW50OiAxNixcbiAgdG91cm5hbWVudF9kZXRhaWxzOiAxNyxcbiAgbWF0Y2hfb2JqZWN0X3R5cGU6IDE4LFxuICBnYW1lOiAxOVxufTtcblxuQ2hhaW5UeXBlcy5pbXBsX29iamVjdF90eXBlID0ge1xuICBnbG9iYWxfcHJvcGVydHk6IDAsXG4gIGR5bmFtaWNfZ2xvYmFsX3Byb3BlcnR5OiAxLFxuICBpbmRleF9tZXRhOiAyLFxuICBhc3NldF9keW5hbWljX2RhdGE6IDMsXG4gIGFzc2V0X2JpdGFzc2V0X2RhdGE6IDQsXG4gIGFjY291bnRfYmFsYW5jZTogNSxcbiAgYWNjb3VudF9zdGF0aXN0aWNzOiA2LFxuICB0cmFuc2FjdGlvbjogNyxcbiAgYmxvY2tfc3VtbWFyeTogOCxcbiAgYWNjb3VudF90cmFuc2FjdGlvbl9oaXN0b3J5OiA5LFxuICBibGluZGVkX2JhbGFuY2U6IDEwLFxuICBjaGFpbl9wcm9wZXJ0eTogMTEsXG4gIHdpdG5lc3Nfc2NoZWR1bGU6IDEyLFxuICBidWRnZXRfcmVjb3JkOiAxMyxcbiAgc3BlY2lhbF9hdXRob3JpdHk6IDE0LFxuICBidXliYWNrOiAxNSxcbiAgZmJhX2FjY3VtdWxhdG9yOiAxNixcbiAgYXNzZXRfZGl2aWRlbmRfZGF0YTogMTcsXG4gIHBlbmRpbmdfZGl2aWRlbmRfcGF5b3V0X2JhbGFuY2VfZm9yX2hvbGRlcjogMTgsXG4gIGRpc3RyaWJ1dGVkX2RpdmlkZW5kX2JhbGFuY2VfZGF0YTogMTlcbn07XG5cbkNoYWluVHlwZXMudm90ZV90eXBlID0ge1xuICBjb21taXR0ZWU6IDAsXG4gIHdpdG5lc3M6IDEsXG4gIHdvcmtlcjogMlxufTtcblxuQ2hhaW5UeXBlcy5vcGVyYXRpb25zID0ge1xuICB0cmFuc2ZlcjogMCxcbiAgbGltaXRfb3JkZXJfY3JlYXRlOiAxLFxuICBsaW1pdF9vcmRlcl9jYW5jZWw6IDIsXG4gIGNhbGxfb3JkZXJfdXBkYXRlOiAzLFxuICBmaWxsX29yZGVyOiA0LFxuICBhY2NvdW50X2NyZWF0ZTogNSxcbiAgYWNjb3VudF91cGRhdGU6IDYsXG4gIGFjY291bnRfd2hpdGVsaXN0OiA3LFxuICBhY2NvdW50X3VwZ3JhZGU6IDgsXG4gIGFjY291bnRfdHJhbnNmZXI6IDksXG4gIGFzc2V0X2NyZWF0ZTogMTAsXG4gIGFzc2V0X3VwZGF0ZTogMTEsXG4gIGFzc2V0X3VwZGF0ZV9iaXRhc3NldDogMTIsXG4gIGFzc2V0X3VwZGF0ZV9mZWVkX3Byb2R1Y2VyczogMTMsXG4gIGFzc2V0X2lzc3VlOiAxNCxcbiAgYXNzZXRfcmVzZXJ2ZTogMTUsXG4gIGFzc2V0X2Z1bmRfZmVlX3Bvb2w6IDE2LFxuICBhc3NldF9zZXR0bGU6IDE3LFxuICBhc3NldF9nbG9iYWxfc2V0dGxlOiAxOCxcbiAgYXNzZXRfcHVibGlzaF9mZWVkOiAxOSxcbiAgd2l0bmVzc19jcmVhdGU6IDIwLFxuICB3aXRuZXNzX3VwZGF0ZTogMjEsXG4gIHByb3Bvc2FsX2NyZWF0ZTogMjIsXG4gIHByb3Bvc2FsX3VwZGF0ZTogMjMsXG4gIHByb3Bvc2FsX2RlbGV0ZTogMjQsXG4gIHdpdGhkcmF3X3Blcm1pc3Npb25fY3JlYXRlOiAyNSxcbiAgd2l0aGRyYXdfcGVybWlzc2lvbl91cGRhdGU6IDI2LFxuICB3aXRoZHJhd19wZXJtaXNzaW9uX2NsYWltOiAyNyxcbiAgd2l0aGRyYXdfcGVybWlzc2lvbl9kZWxldGU6IDI4LFxuICBjb21taXR0ZWVfbWVtYmVyX2NyZWF0ZTogMjksXG4gIGNvbW1pdHRlZV9tZW1iZXJfdXBkYXRlOiAzMCxcbiAgY29tbWl0dGVlX21lbWJlcl91cGRhdGVfZ2xvYmFsX3BhcmFtZXRlcnM6IDMxLFxuICB2ZXN0aW5nX2JhbGFuY2VfY3JlYXRlOiAzMixcbiAgdmVzdGluZ19iYWxhbmNlX3dpdGhkcmF3OiAzMyxcbiAgd29ya2VyX2NyZWF0ZTogMzQsXG4gIGN1c3RvbTogMzUsXG4gIGFzc2VydDogMzYsXG4gIGJhbGFuY2VfY2xhaW06IDM3LFxuICBvdmVycmlkZV90cmFuc2ZlcjogMzgsXG4gIHRyYW5zZmVyX3RvX2JsaW5kOiAzOSxcbiAgYmxpbmRfdHJhbnNmZXI6IDQwLFxuICB0cmFuc2Zlcl9mcm9tX2JsaW5kOiA0MSxcbiAgYXNzZXRfc2V0dGxlX2NhbmNlbDogNDIsXG4gIGFzc2V0X2NsYWltX2ZlZXM6IDQzLFxuICBmYmFfZGlzdHJpYnV0ZV9vcGVyYXRpb246IDQ0LFxuICB0b3VybmFtZW50X2NyZWF0ZTogNDUsXG4gIHRvdXJuYW1lbnRfam9pbjogNDYsXG4gIGdhbWVfbW92ZTogNDcsXG4gIGFzc2V0X3VwZGF0ZV9kaXZpZGVuZDogNDgsXG4gIGFzc2V0X2RpdmlkZW5kX2Rpc3RyaWJ1dGlvbjogNDlcbn07XG5cbm1vZHVsZS5leHBvcnRzID0gQ2hhaW5UeXBlczsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoJ2J5dGVidWZmZXInKSxcbiAgICBMb25nID0gX3JlcXVpcmUuTG9uZztcblxudmFyIHYgPSByZXF1aXJlKCcuLi8uLi9zZXJpYWxpemVyL3NyYy9TZXJpYWxpemVyVmFsaWRhdGlvbicpO1xuXG52YXIgREJfTUFYX0lOU1RBTkNFX0lEID0gTG9uZy5mcm9tTnVtYmVyKE1hdGgucG93KDIsIDQ4KSAtIDEpO1xuXG52YXIgT2JqZWN0SWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gT2JqZWN0SWQoc3BhY2UsIHR5cGUsIGluc3RhbmNlKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBPYmplY3RJZCk7XG5cbiAgICAgICAgdGhpcy5zcGFjZSA9IHNwYWNlO1xuICAgICAgICB0aGlzLnR5cGUgPSB0eXBlO1xuICAgICAgICB0aGlzLmluc3RhbmNlID0gaW5zdGFuY2U7XG4gICAgICAgIHZhciBpbnN0YW5jZV9zdHJpbmcgPSB0aGlzLmluc3RhbmNlLnRvU3RyaW5nKCk7XG4gICAgICAgIHZhciBfT2JqZWN0SWQgPSB0aGlzLnNwYWNlICsgJy4nICsgdGhpcy50eXBlICsgJy4nICsgaW5zdGFuY2Vfc3RyaW5nO1xuICAgICAgICBpZiAoIXYuaXNfZGlnaXRzKGluc3RhbmNlX3N0cmluZykpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyAoJ0ludmFsaWQgb2JqZWN0IGlkICcgKyBfT2JqZWN0SWQpKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBfY3JlYXRlQ2xhc3MoT2JqZWN0SWQsIFt7XG4gICAgICAgIGtleTogJ3RvTG9uZycsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b0xvbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gTG9uZy5mcm9tTnVtYmVyKHRoaXMuc3BhY2UpLnNoaWZ0TGVmdCg1Nikub3IoTG9uZy5mcm9tTnVtYmVyKHRoaXMudHlwZSkuc2hpZnRMZWZ0KDQ4KS5vcih0aGlzLmluc3RhbmNlKSk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2FwcGVuZEJ5dGVCdWZmZXInLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gYXBwZW5kQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgICAgICByZXR1cm4gYi53cml0ZVVpbnQ2NCh0aGlzLnRvTG9uZygpKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndG9TdHJpbmcnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdG9TdHJpbmcoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zcGFjZSArICcuJyArIHRoaXMudHlwZSArICcuJyArIHRoaXMuaW5zdGFuY2UudG9TdHJpbmcoKTtcbiAgICAgICAgfVxuICAgIH1dLCBbe1xuICAgICAgICBrZXk6ICdmcm9tU3RyaW5nJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21TdHJpbmcodmFsdWUpIHtcbiAgICAgICAgICAgIGlmICh2YWx1ZS5zcGFjZSAhPT0gdW5kZWZpbmVkICYmIHZhbHVlLnR5cGUgIT09IHVuZGVmaW5lZCAmJiB2YWx1ZS5pbnN0YW5jZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcGFyYW1zID0gdi5yZXF1aXJlX21hdGNoKC9eKFswLTldKylcXC4oWzAtOV0rKVxcLihbMC05XSspJC8sIHYucmVxdWlyZWQodmFsdWUsIFwiT2JqZWN0SWRcIiksIFwiT2JqZWN0SWRcIik7XG4gICAgICAgICAgICByZXR1cm4gbmV3IE9iamVjdElkKHBhcnNlSW50KHBhcmFtc1sxXSksIHBhcnNlSW50KHBhcmFtc1syXSksIExvbmcuZnJvbVN0cmluZyhwYXJhbXNbM10pKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnZnJvbUxvbmcnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZnJvbUxvbmcobG9uZykge1xuICAgICAgICAgICAgdmFyIHNwYWNlID0gbG9uZy5zaGlmdFJpZ2h0KDU2KS50b0ludCgpO1xuICAgICAgICAgICAgdmFyIHR5cGUgPSBsb25nLnNoaWZ0UmlnaHQoNDgpLnRvSW50KCkgJiAweDAwZmY7XG4gICAgICAgICAgICB2YXIgaW5zdGFuY2UgPSBsb25nLmFuZChEQl9NQVhfSU5TVEFOQ0VfSUQpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBPYmplY3RJZChzcGFjZSwgdHlwZSwgaW5zdGFuY2UpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdmcm9tQnl0ZUJ1ZmZlcicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgICAgICByZXR1cm4gT2JqZWN0SWQuZnJvbUxvbmcoYi5yZWFkVWludDY0KCkpO1xuICAgICAgICB9XG4gICAgfV0pO1xuXG4gICAgcmV0dXJuIE9iamVjdElkO1xufSgpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IE9iamVjdElkOyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX3NsaWNlZFRvQXJyYXkgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIHNsaWNlSXRlcmF0b3IoYXJyLCBpKSB7IHZhciBfYXJyID0gW107IHZhciBfbiA9IHRydWU7IHZhciBfZCA9IGZhbHNlOyB2YXIgX2UgPSB1bmRlZmluZWQ7IHRyeSB7IGZvciAodmFyIF9pID0gYXJyW1N5bWJvbC5pdGVyYXRvcl0oKSwgX3M7ICEoX24gPSAoX3MgPSBfaS5uZXh0KCkpLmRvbmUpOyBfbiA9IHRydWUpIHsgX2Fyci5wdXNoKF9zLnZhbHVlKTsgaWYgKGkgJiYgX2Fyci5sZW5ndGggPT09IGkpIGJyZWFrOyB9IH0gY2F0Y2ggKGVycikgeyBfZCA9IHRydWU7IF9lID0gZXJyOyB9IGZpbmFsbHkgeyB0cnkgeyBpZiAoIV9uICYmIF9pW1wicmV0dXJuXCJdKSBfaVtcInJldHVyblwiXSgpOyB9IGZpbmFsbHkgeyBpZiAoX2QpIHRocm93IF9lOyB9IH0gcmV0dXJuIF9hcnI7IH0gcmV0dXJuIGZ1bmN0aW9uIChhcnIsIGkpIHsgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgeyByZXR1cm4gYXJyOyB9IGVsc2UgaWYgKFN5bWJvbC5pdGVyYXRvciBpbiBPYmplY3QoYXJyKSkgeyByZXR1cm4gc2xpY2VJdGVyYXRvcihhcnIsIGkpOyB9IGVsc2UgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBhdHRlbXB0IHRvIGRlc3RydWN0dXJlIG5vbi1pdGVyYWJsZSBpbnN0YW5jZVwiKTsgfSB9OyB9KCk7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBhc3NlcnQgPSByZXF1aXJlKFwiYXNzZXJ0XCIpO1xuXG52YXIgX3JlcXVpcmUgPSByZXF1aXJlKFwiLi4vLi4vZWNjXCIpLFxuICAgIFNpZ25hdHVyZSA9IF9yZXF1aXJlLlNpZ25hdHVyZSxcbiAgICBQdWJsaWNLZXkgPSBfcmVxdWlyZS5QdWJsaWNLZXksXG4gICAgaGFzaCA9IF9yZXF1aXJlLmhhc2g7XG5cbnZhciBfcmVxdWlyZTIgPSByZXF1aXJlKFwiLi4vLi4vc2VyaWFsaXplclwiKSxcbiAgICBvcHMgPSBfcmVxdWlyZTIub3BzO1xuXG52YXIgX3JlcXVpcmUzID0gcmVxdWlyZSgncGVlcnBsYXlzanMtd3MnKSxcbiAgICBBcGlzID0gX3JlcXVpcmUzLkFwaXMsXG4gICAgQ2hhaW5Db25maWcgPSBfcmVxdWlyZTMuQ2hhaW5Db25maWc7XG5cbnZhciBDaGFpblR5cGVzID0gcmVxdWlyZSgnLi9DaGFpblR5cGVzJyk7XG52YXIgaGVhZF9ibG9ja190aW1lX3N0cmluZztcblxudmFyIFRyYW5zYWN0aW9uQnVpbGRlciA9IGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUcmFuc2FjdGlvbkJ1aWxkZXIoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBUcmFuc2FjdGlvbkJ1aWxkZXIpO1xuXG4gICAgICAgIHRoaXMucmVmX2Jsb2NrX251bSA9IDA7XG4gICAgICAgIHRoaXMucmVmX2Jsb2NrX3ByZWZpeCA9IDA7XG4gICAgICAgIHRoaXMuZXhwaXJhdGlvbiA9IDA7XG4gICAgICAgIHRoaXMub3BlcmF0aW9ucyA9IFtdO1xuICAgICAgICB0aGlzLnNpZ25hdHVyZXMgPSBbXTtcbiAgICAgICAgdGhpcy5zaWduZXJfcHJpdmF0ZV9rZXlzID0gW107XG5cbiAgICAgICAgLy8gc2VtaS1wcml2YXRlIG1ldGhvZCBiaW5kaW5nc1xuICAgICAgICB0aGlzLl9icm9hZGNhc3QgPSBfYnJvYWRjYXN0LmJpbmQodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICAgIEBhcmcge3N0cmluZ30gbmFtZSAtIGxpa2UgXCJ0cmFuc2ZlclwiXG4gICAgICAgIEBhcmcge29iamVjdH0gb3BlcmF0aW9uIC0gSlNPTiBtYXRjaGNoaW5nIHRoZSBvcGVyYXRpb24ncyBmb3JtYXRcbiAgICAqL1xuXG5cbiAgICBfY3JlYXRlQ2xhc3MoVHJhbnNhY3Rpb25CdWlsZGVyLCBbe1xuICAgICAgICBrZXk6IFwiYWRkX3R5cGVfb3BlcmF0aW9uXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBhZGRfdHlwZV9vcGVyYXRpb24obmFtZSwgb3BlcmF0aW9uKSB7XG4gICAgICAgICAgICB0aGlzLmFkZF9vcGVyYXRpb24odGhpcy5nZXRfdHlwZV9vcGVyYXRpb24obmFtZSwgb3BlcmF0aW9uKSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICAgIFRoaXMgZG9lcyBpdCBhbGw6IHNldCBmZWVzLCBmaW5hbGl6ZSwgc2lnbiwgYW5kIGJyb2FkY2FzdCAoaWYgd2FudGVkKS5cbiAgICAgICAgICAgICBAYXJnIHtDb25maWRlbnRpYWxXYWxsZXR9IGN3YWxsZXQgLSBtdXN0IGJlIHVubG9ja2VkLCB1c2VkIHRvIGdhdGhlciBzaWduaW5nIGtleXNcbiAgICAgICAgICAgICBAYXJnIHthcnJheTxzdHJpbmc+fSBbc2lnbmVyX3B1YmtleXMgPSBudWxsXSAtIE9wdGlvbmFsIFtcIkdQSEFiYzlEZWYwLi4uXCIsIC4uLl0uICBUaGVzZSBhcmUgYWRkaXRpb25hbCBzaWduaW5nIGtleXMuICBTb21lIGJhbGFuY2UgY2xhaW1zIHJlcXVpcmUgcHJvcHJpdGFyeSBhZGRyZXNzIGZvcm1hdHMsIHRoZSB3aXRuZXNzIG5vZGUgY2FuJ3QgdGVsbCB1cyB3aGljaCBvbmVzIGFyZSBuZWVkZWQgc28gdGhleSBtdXN0IGJlIHBhc3NlZCBpbi4gIElmIHRoZSB3aXRuZXNzIG5vZGUgY2FuIGZpZ3VyZSBvdXQgYSBzaWduaW5nIGtleSAobW9zdGx5IGFsbCBvdGhlciB0cmFuc2FjdGlvbnMpLCBpdCBzaG91bGQgbm90IGJlIHBhc3NlZCBpbiBoZXJlLlxuICAgICAgICAgICAgIEBhcmcge2Jvb2xlYW59IFticm9hZGNhc3QgPSBmYWxzZV1cbiAgICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcInByb2Nlc3NfdHJhbnNhY3Rpb25cIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHByb2Nlc3NfdHJhbnNhY3Rpb24oY3dhbGxldCkge1xuICAgICAgICAgICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgICAgICAgICAgdmFyIHNpZ25lcl9wdWJrZXlzID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBudWxsO1xuICAgICAgICAgICAgdmFyIGJyb2FkY2FzdCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogZmFsc2U7XG5cblxuICAgICAgICAgICAgdmFyIHdhbGxldF9vYmplY3QgPSBjd2FsbGV0LndhbGxldC53YWxsZXRfb2JqZWN0O1xuICAgICAgICAgICAgaWYgKEFwaXMuaW5zdGFuY2UoKS5jaGFpbl9pZCAhPT0gd2FsbGV0X29iamVjdC5nZXQoXCJjaGFpbl9pZFwiKSkgcmV0dXJuIFByb21pc2UucmVqZWN0KFwiTWlzbWF0Y2hlZCBjaGFpbl9pZDsgZXhwZWN0aW5nIFwiICsgd2FsbGV0X29iamVjdC5nZXQoXCJjaGFpbl9pZFwiKSArIFwiLCBidXQgZ290IFwiICsgQXBpcy5pbnN0YW5jZSgpLmNoYWluX2lkKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuc2V0X3JlcXVpcmVkX2ZlZXMoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgc2lnbmVyX3B1YmtleXNfYWRkZWQgPSB7fTtcbiAgICAgICAgICAgICAgICBpZiAoc2lnbmVyX3B1YmtleXMpIHtcblxuICAgICAgICAgICAgICAgICAgICAvLyBCYWxhbmNlIGNsYWltcyBhcmUgYnkgYWRkcmVzcywgb25seSB0aGUgcHJpdmF0ZVxuICAgICAgICAgICAgICAgICAgICAvLyBrZXkgaG9sZGVyIGNhbiBrbm93IGFib3V0IHRoZXNlIGFkZGl0aW9uYWxcbiAgICAgICAgICAgICAgICAgICAgLy8gcG90ZW50aWFsIGtleXMuXG4gICAgICAgICAgICAgICAgICAgIHZhciBwdWJrZXlzID0gY3dhbGxldC5nZXRQdWJrZXlzX2hhdmluZ19Qcml2YXRlS2V5KHNpZ25lcl9wdWJrZXlzKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwdWJrZXlzLmxlbmd0aCkgdGhyb3cgbmV3IEVycm9yKFwiTWlzc2luZyBzaWduaW5nIGtleVwiKTtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHZhciBfZGlkSXRlcmF0b3JFcnJvciA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB2YXIgX2l0ZXJhdG9yRXJyb3IgPSB1bmRlZmluZWQ7XG5cbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIF9pdGVyYXRvciA9IHB1YmtleXNbU3ltYm9sLml0ZXJhdG9yXSgpLCBfc3RlcDsgIShfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uID0gKF9zdGVwID0gX2l0ZXJhdG9yLm5leHQoKSkuZG9uZSk7IF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24gPSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHB1YmtleV9zdHJpbmcgPSBfc3RlcC52YWx1ZTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcml2YXRlX2tleSA9IGN3YWxsZXQuZ2V0UHJpdmF0ZUtleShwdWJrZXlfc3RyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5hZGRfc2lnbmVyKHByaXZhdGVfa2V5LCBwdWJrZXlfc3RyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWduZXJfcHVia2V5c19hZGRlZFtwdWJrZXlfc3RyaW5nXSA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2RpZEl0ZXJhdG9yRXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgX2l0ZXJhdG9yRXJyb3IgPSBlcnI7XG4gICAgICAgICAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbiAmJiBfaXRlcmF0b3IucmV0dXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9pdGVyYXRvci5yZXR1cm4oKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChfZGlkSXRlcmF0b3JFcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBfaXRlcmF0b3JFcnJvcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gX3RoaXMuZ2V0X3BvdGVudGlhbF9zaWduYXR1cmVzKCkudGhlbihmdW5jdGlvbiAoX3JlZikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcHVia2V5cyA9IF9yZWYucHVia2V5cyxcbiAgICAgICAgICAgICAgICAgICAgICAgIGFkZHlzID0gX3JlZi5hZGR5cztcblxuICAgICAgICAgICAgICAgICAgICB2YXIgbXlfcHVia2V5cyA9IGN3YWxsZXQuZ2V0UHVia2V5c19oYXZpbmdfUHJpdmF0ZUtleShwdWJrZXlzLCBhZGR5cyk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy97Ly9UZXN0aW5nIG9ubHksIGRvbid0IHNlbmQgQWxsIHB1YmxpYyBrZXlzIVxuICAgICAgICAgICAgICAgICAgICAvLyAgICB2YXIgcHVia2V5c19hbGwgPSBQcml2YXRlS2V5U3RvcmUuZ2V0UHVia2V5cygpIC8vIEFsbCBwdWJsaWMga2V5c1xuICAgICAgICAgICAgICAgICAgICAvLyAgICB0aGlzLmdldF9yZXF1aXJlZF9zaWduYXR1cmVzKHB1YmtleXNfYWxsKS50aGVuKCByZXF1aXJlZF9wdWJrZXlfc3RyaW5ncyA9PlxuICAgICAgICAgICAgICAgICAgICAvLyAgICAgICAgY29uc29sZS5sb2coJ2dldF9yZXF1aXJlZF9zaWduYXR1cmVzIGFsbFxcdCcscmVxdWlyZWRfcHVia2V5X3N0cmluZ3Muc29ydCgpLCBwdWJrZXlzX2FsbCkpXG4gICAgICAgICAgICAgICAgICAgIC8vICAgIHRoaXMuZ2V0X3JlcXVpcmVkX3NpZ25hdHVyZXMobXlfcHVia2V5cykudGhlbiggcmVxdWlyZWRfcHVia2V5X3N0cmluZ3MgPT5cbiAgICAgICAgICAgICAgICAgICAgLy8gICAgICAgIGNvbnNvbGUubG9nKCdnZXRfcmVxdWlyZWRfc2lnbmF0dXJlcyBub3JtYWxcXHQnLHJlcXVpcmVkX3B1YmtleV9zdHJpbmdzLnNvcnQoKSwgcHVia2V5cykpXG4gICAgICAgICAgICAgICAgICAgIC8vfVxuXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBfdGhpcy5nZXRfcmVxdWlyZWRfc2lnbmF0dXJlcyhteV9wdWJrZXlzKS50aGVuKGZ1bmN0aW9uIChyZXF1aXJlZF9wdWJrZXlzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjIgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9kaWRJdGVyYXRvckVycm9yMiA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF9pdGVyYXRvckVycm9yMiA9IHVuZGVmaW5lZDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBfaXRlcmF0b3IyID0gcmVxdWlyZWRfcHVia2V5c1tTeW1ib2wuaXRlcmF0b3JdKCksIF9zdGVwMjsgIShfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMiA9IChfc3RlcDIgPSBfaXRlcmF0b3IyLm5leHQoKSkuZG9uZSk7IF9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24yID0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgX3B1YmtleV9zdHJpbmcgPSBfc3RlcDIudmFsdWU7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNpZ25lcl9wdWJrZXlzX2FkZGVkW19wdWJrZXlfc3RyaW5nXSkgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwcml2YXRlX2tleSA9IGN3YWxsZXQuZ2V0UHJpdmF0ZUtleShfcHVia2V5X3N0cmluZyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghcHJpdmF0ZV9rZXkpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHNob3VsZCBub3QgaGFwcGVuLCBnZXRfcmVxdWlyZWRfc2lnbmF0dXJlcyB3aWxsIG9ubHlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHJldHVybmVkIGtleXMgZnJvbSBteV9wdWJrZXlzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNaXNzaW5nIHNpZ25pbmcga2V5IGZvciBcIiArIF9wdWJrZXlfc3RyaW5nKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX3RoaXMuYWRkX3NpZ25lcihwcml2YXRlX2tleSwgX3B1YmtleV9zdHJpbmcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9kaWRJdGVyYXRvckVycm9yMiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX2l0ZXJhdG9yRXJyb3IyID0gZXJyO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIV9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24yICYmIF9pdGVyYXRvcjIucmV0dXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBfaXRlcmF0b3IyLnJldHVybigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9kaWRJdGVyYXRvckVycm9yMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgX2l0ZXJhdG9yRXJyb3IyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9KS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGJyb2FkY2FzdCA/IF90aGlzLmJyb2FkY2FzdCgpIDogX3RoaXMuc2VyaWFsaXplKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBUeXBpY2FsbHkgdGhpcyBpcyBjYWxsZWQgYXV0b21hdGljYWxseSBqdXN0IHByaW9yIHRvIHNpZ25pbmcuICBPbmNlIGZpbmFsaXplZCB0aGlzIHRyYW5zYWN0aW9uIGNhbiBub3QgYmUgY2hhbmdlZC4gKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImZpbmFsaXplXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmaW5hbGl6ZSgpIHtcbiAgICAgICAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuXG4gICAgICAgICAgICAgICAgaWYgKF90aGlzMi50cl9idWZmZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWxyZWFkeSBmaW5hbGl6ZWRcIik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzb2x2ZShBcGlzLmluc3RhbmNlKCkuZGJfYXBpKCkuZXhlYyhcImdldF9vYmplY3RzXCIsIFtbXCIyLjEuMFwiXV0pLnRoZW4oZnVuY3Rpb24gKHIpIHtcbiAgICAgICAgICAgICAgICAgICAgaGVhZF9ibG9ja190aW1lX3N0cmluZyA9IHJbMF0udGltZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzMi5leHBpcmF0aW9uID09PSAwKSBfdGhpczIuZXhwaXJhdGlvbiA9IGJhc2VfZXhwaXJhdGlvbl9zZWMoKSArIENoYWluQ29uZmlnLmV4cGlyZV9pbl9zZWNzO1xuICAgICAgICAgICAgICAgICAgICBfdGhpczIucmVmX2Jsb2NrX251bSA9IHJbMF0uaGVhZF9ibG9ja19udW1iZXIgJiAweEZGRkY7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMi5yZWZfYmxvY2tfcHJlZml4ID0gbmV3IEJ1ZmZlcihyWzBdLmhlYWRfYmxvY2tfaWQsICdoZXgnKS5yZWFkVUludDMyTEUoNCk7XG4gICAgICAgICAgICAgICAgICAgIC8vREVCVUcgY29uc29sZS5sb2coXCJyZWZfYmxvY2tcIixAcmVmX2Jsb2NrX251bSxAcmVmX2Jsb2NrX3ByZWZpeCxyKVxuXG4gICAgICAgICAgICAgICAgICAgIHZhciBpdGVyYWJsZSA9IF90aGlzMi5vcGVyYXRpb25zO1xuICAgICAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgb3A7IGkgPCBpdGVyYWJsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgb3AgPSBpdGVyYWJsZVtpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcFsxXVtcImZpbmFsaXplXCJdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3BbMV0uZmluYWxpemUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIF90eXBlID0gb3BzLm9wZXJhdGlvbi5zdF9vcGVyYXRpb25zW29wWzBdXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBoZXhCdWZmZXIgPSBfdHlwZS50b0J1ZmZlcihvcFsxXSkudG9TdHJpbmcoXCJoZXhcIik7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhcIk9wZXJhdGlvbiAlczogJU8gPT4gJXMgKCVkIGJ5dGVzKVwiLCBfdHlwZS5vcGVyYXRpb25fbmFtZSwgb3BbMV0sIGhleEJ1ZmZlciwgaGV4QnVmZmVyLmxlbmd0aCAvIDIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIF90aGlzMi50cl9idWZmZXIgPSBvcHMudHJhbnNhY3Rpb24udG9CdWZmZXIoX3RoaXMyKTtcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBAcmV0dXJuIHtzdHJpbmd9IGhleCB0cmFuc2FjdGlvbiBJRCAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6IFwiaWRcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGlkKCkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLnRyX2J1ZmZlcikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIm5vdCBmaW5hbGl6ZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gaGFzaC5zaGEyNTYodGhpcy50cl9idWZmZXIpLnRvU3RyaW5nKCdoZXgnKS5zdWJzdHJpbmcoMCwgNDApO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAgICBUeXBpY2FsbHkgb25lIHdpbGwgdXNlIHtAbGluayB0aGlzLmFkZF90eXBlX29wZXJhdGlvbn0gaW5zdGVhZC5cbiAgICAgICAgICAgIEBhcmcge2FycmF5fSBvcGVyYXRpb24gLSBbb3BlcmF0aW9uX2lkLCBvcGVyYXRpb25dXG4gICAgICAgICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJhZGRfb3BlcmF0aW9uXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBhZGRfb3BlcmF0aW9uKG9wZXJhdGlvbikge1xuICAgICAgICAgICAgaWYgKHRoaXMudHJfYnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWxyZWFkeSBmaW5hbGl6ZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhc3NlcnQob3BlcmF0aW9uLCBcIm9wZXJhdGlvblwiKTtcbiAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShvcGVyYXRpb24pKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRXhwZWN0aW5nIGFycmF5IFtvcGVyYXRpb25faWQsIG9wZXJhdGlvbl1cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLm9wZXJhdGlvbnMucHVzaChvcGVyYXRpb24pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6IFwiZ2V0X3R5cGVfb3BlcmF0aW9uXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRfdHlwZV9vcGVyYXRpb24obmFtZSwgb3BlcmF0aW9uKSB7XG4gICAgICAgICAgICBpZiAodGhpcy50cl9idWZmZXIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhbHJlYWR5IGZpbmFsaXplZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzc2VydChuYW1lLCBcIm5hbWVcIik7XG4gICAgICAgICAgICBhc3NlcnQob3BlcmF0aW9uLCBcIm9wZXJhdGlvblwiKTtcbiAgICAgICAgICAgIHZhciBfdHlwZSA9IG9wc1tuYW1lXTtcbiAgICAgICAgICAgIGFzc2VydChfdHlwZSwgXCJVbmtub3duIG9wZXJhdGlvbiBcIiArIG5hbWUpO1xuICAgICAgICAgICAgdmFyIG9wZXJhdGlvbl9pZCA9IENoYWluVHlwZXMub3BlcmF0aW9uc1tfdHlwZS5vcGVyYXRpb25fbmFtZV07XG4gICAgICAgICAgICBpZiAob3BlcmF0aW9uX2lkID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJ1bmtub3duIG9wZXJhdGlvbjogXCIgKyBfdHlwZS5vcGVyYXRpb25fbmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW9wZXJhdGlvbi5mZWUpIHtcbiAgICAgICAgICAgICAgICBvcGVyYXRpb24uZmVlID0geyBhbW91bnQ6IDAsIGFzc2V0X2lkOiAwIH07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobmFtZSA9PT0gJ3Byb3Bvc2FsX2NyZWF0ZScpIHtcbiAgICAgICAgICAgICAgICBvcGVyYXRpb24uZXhwaXJhdGlvbl90aW1lIHx8IChvcGVyYXRpb24uZXhwaXJhdGlvbl90aW1lID0gYmFzZV9leHBpcmF0aW9uX3NlYygpICsgQ2hhaW5Db25maWcuZXhwaXJlX2luX3NlY3NfcHJvcG9zYWwpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG9wZXJhdGlvbl9pbnN0YW5jZSA9IF90eXBlLmZyb21PYmplY3Qob3BlcmF0aW9uKTtcbiAgICAgICAgICAgIHJldHVybiBbb3BlcmF0aW9uX2lkLCBvcGVyYXRpb25faW5zdGFuY2VdO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqIG9wdGlvbmFsOiB0aGVyZSBpcyBhIGRlYWZ1bHQgZXhwaXJhdGlvbiAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6IFwic2V0X2V4cGlyZV9zZWNvbmRzXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzZXRfZXhwaXJlX3NlY29uZHMoc2VjKSB7XG4gICAgICAgICAgICBpZiAodGhpcy50cl9idWZmZXIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhbHJlYWR5IGZpbmFsaXplZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmV4cGlyYXRpb24gPSBiYXNlX2V4cGlyYXRpb25fc2VjKCkgKyBzZWM7XG4gICAgICAgIH1cblxuICAgICAgICAvKiBXcmFwcyB0aGlzIHRyYW5zYWN0aW9uIGluIGEgcHJvcG9zYWxfY3JlYXRlIHRyYW5zYWN0aW9uICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJwcm9wb3NlXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBwcm9wb3NlKHByb3Bvc2FsX2NyZWF0ZV9vcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAodGhpcy50cl9idWZmZXIpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhbHJlYWR5IGZpbmFsaXplZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5vcGVyYXRpb25zLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImFkZCBvcGVyYXRpb24gZmlyc3RcIik7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGFzc2VydChwcm9wb3NhbF9jcmVhdGVfb3B0aW9ucywgXCJwcm9wb3NhbF9jcmVhdGVfb3B0aW9uc1wiKTtcbiAgICAgICAgICAgIGFzc2VydChwcm9wb3NhbF9jcmVhdGVfb3B0aW9ucy5mZWVfcGF5aW5nX2FjY291bnQsIFwicHJvcG9zYWxfY3JlYXRlX29wdGlvbnMuZmVlX3BheWluZ19hY2NvdW50XCIpO1xuXG4gICAgICAgICAgICB2YXIgcHJvcG9zZWRfb3BzID0gdGhpcy5vcGVyYXRpb25zLm1hcChmdW5jdGlvbiAob3ApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBvcDogb3AgfTtcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICB0aGlzLm9wZXJhdGlvbnMgPSBbXTtcbiAgICAgICAgICAgIHRoaXMuc2lnbmF0dXJlcyA9IFtdO1xuICAgICAgICAgICAgdGhpcy5zaWduZXJfcHJpdmF0ZV9rZXlzID0gW107XG4gICAgICAgICAgICBwcm9wb3NhbF9jcmVhdGVfb3B0aW9ucy5wcm9wb3NlZF9vcHMgPSBwcm9wb3NlZF9vcHM7XG4gICAgICAgICAgICB0aGlzLmFkZF90eXBlX29wZXJhdGlvbihcInByb3Bvc2FsX2NyZWF0ZVwiLCBwcm9wb3NhbF9jcmVhdGVfb3B0aW9ucyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImhhc19wcm9wb3NlZF9vcGVyYXRpb25cIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGhhc19wcm9wb3NlZF9vcGVyYXRpb24oKSB7XG4gICAgICAgICAgICB2YXIgaGFzUHJvcG9zZWQgPSBmYWxzZTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy5vcGVyYXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKFwicHJvcG9zZWRfb3BzXCIgaW4gdGhpcy5vcGVyYXRpb25zW2ldWzFdKSB7XG4gICAgICAgICAgICAgICAgICAgIGhhc1Byb3Bvc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gaGFzUHJvcG9zZWQ7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogb3B0aW9uYWw6IHRoZSBmZWVzIGNhbiBiZSBvYnRhaW5lZCBmcm9tIHRoZSB3aXRuZXNzIG5vZGUgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcInNldF9yZXF1aXJlZF9mZWVzXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzZXRfcmVxdWlyZWRfZmVlcyhhc3NldF9pZCkge1xuICAgICAgICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgICAgICAgIHZhciBmZWVfcG9vbDtcbiAgICAgICAgICAgIGlmICh0aGlzLnRyX2J1ZmZlcikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImFscmVhZHkgZmluYWxpemVkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCF0aGlzLm9wZXJhdGlvbnMubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWRkIG9wZXJhdGlvbnMgZmlyc3RcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgb3BlcmF0aW9ucyA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIG9wOyBpIDwgdGhpcy5vcGVyYXRpb25zLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgb3AgPSB0aGlzLm9wZXJhdGlvbnNbaV07XG4gICAgICAgICAgICAgICAgb3BlcmF0aW9ucy5wdXNoKG9wcy5vcGVyYXRpb24udG9PYmplY3Qob3ApKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFhc3NldF9pZCkge1xuICAgICAgICAgICAgICAgIHZhciBvcDFfZmVlID0gb3BlcmF0aW9uc1swXVsxXS5mZWU7XG4gICAgICAgICAgICAgICAgaWYgKG9wMV9mZWUgJiYgb3AxX2ZlZS5hc3NldF9pZCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBhc3NldF9pZCA9IG9wMV9mZWUuYXNzZXRfaWQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXRfaWQgPSBcIjEuMy4wXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgcHJvbWlzZXMgPSBbQXBpcy5pbnN0YW5jZSgpLmRiX2FwaSgpLmV4ZWMoXCJnZXRfcmVxdWlyZWRfZmVlc1wiLCBbb3BlcmF0aW9ucywgYXNzZXRfaWRdKV07XG5cbiAgICAgICAgICAgIHZhciBmZWVBc3NldFByb21pc2UgPSBudWxsO1xuICAgICAgICAgICAgaWYgKGFzc2V0X2lkICE9PSBcIjEuMy4wXCIpIHtcbiAgICAgICAgICAgICAgICAvLyBUaGlzIGhhbmRsZXMgdGhlIGZhbGxiYWNrIHRvIHBheWluZyBmZWVzIGluIEJUUyBpZiB0aGUgZmVlIHBvb2wgaXMgZW1wdHkuXG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChBcGlzLmluc3RhbmNlKCkuZGJfYXBpKCkuZXhlYyhcImdldF9yZXF1aXJlZF9mZWVzXCIsIFtvcGVyYXRpb25zLCBcIjEuMy4wXCJdKSk7XG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChBcGlzLmluc3RhbmNlKCkuZGJfYXBpKCkuZXhlYyhcImdldF9vYmplY3RzXCIsIFtbYXNzZXRfaWRdXSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24gKHJlc3VsdHMpIHtcbiAgICAgICAgICAgICAgICB2YXIgX3Jlc3VsdHMgPSBfc2xpY2VkVG9BcnJheShyZXN1bHRzLCAzKSxcbiAgICAgICAgICAgICAgICAgICAgZmVlcyA9IF9yZXN1bHRzWzBdLFxuICAgICAgICAgICAgICAgICAgICBjb3JlRmVlcyA9IF9yZXN1bHRzWzFdLFxuICAgICAgICAgICAgICAgICAgICBhc3NldCA9IF9yZXN1bHRzWzJdO1xuXG4gICAgICAgICAgICAgICAgYXNzZXQgPSBhc3NldCA/IGFzc2V0WzBdIDogbnVsbDtcblxuICAgICAgICAgICAgICAgIHZhciBkeW5hbWljUHJvbWlzZSA9IGFzc2V0X2lkICE9PSBcIjEuMy4wXCIgJiYgYXNzZXQgPyBBcGlzLmluc3RhbmNlKCkuZGJfYXBpKCkuZXhlYyhcImdldF9vYmplY3RzXCIsIFtbYXNzZXQuZHluYW1pY19hc3NldF9kYXRhX2lkXV0pIDogbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gZHluYW1pY1Byb21pc2UudGhlbihmdW5jdGlvbiAoZHluYW1pY09iamVjdCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoYXNzZXRfaWQgIT09IFwiMS4zLjBcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgZmVlX3Bvb2wgPSBkeW5hbWljT2JqZWN0ID8gZHluYW1pY09iamVjdFswXS5mZWVfcG9vbCA6IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdG90YWxGZWVzID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGogPSAwLCBmZWU7IGogPCBjb3JlRmVlcy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlZSA9IGNvcmVGZWVzW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvdGFsRmVlcyArPSBmZWUuYW1vdW50O1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodG90YWxGZWVzID4gcGFyc2VJbnQoZmVlX3Bvb2wsIDEwKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlZXMgPSBjb3JlRmVlcztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NldF9pZCA9IFwiMS4zLjBcIjtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFByb3Bvc2VkIHRyYW5zYWN0aW9ucyBuZWVkIHRvIGJlIGZsYXR0ZW5lZFxuICAgICAgICAgICAgICAgICAgICB2YXIgZmxhdF9hc3NldHMgPSBbXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZsYXR0ZW4gPSBmdW5jdGlvbiBmbGF0dGVuKG9iaikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkob2JqKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIGsgPSAwLCBpdGVtOyBrIDwgb2JqLmxlbmd0aDsgaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGl0ZW0gPSBvYmpba107XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZsYXR0ZW4oaXRlbSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmbGF0X2Fzc2V0cy5wdXNoKG9iaik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgICAgIGZsYXR0ZW4oZmVlcyk7XG5cbiAgICAgICAgICAgICAgICAgICAgdmFyIGFzc2V0X2luZGV4ID0gMDtcblxuICAgICAgICAgICAgICAgICAgICB2YXIgc2V0X2ZlZSA9IGZ1bmN0aW9uIHNldF9mZWUob3BlcmF0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW9wZXJhdGlvbi5mZWUgfHwgb3BlcmF0aW9uLmZlZS5hbW91bnQgPT09IDAgfHwgb3BlcmF0aW9uLmZlZS5hbW91bnQudG9TdHJpbmcgJiYgb3BlcmF0aW9uLmZlZS5hbW91bnQudG9TdHJpbmcoKSA9PT0gXCIwXCIgLy8gTG9uZ1xuICAgICAgICAgICAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9wZXJhdGlvbi5mZWUgPSBmbGF0X2Fzc2V0c1thc3NldF9pbmRleF07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKFwibmV3IG9wZXJhdGlvbi5mZWVcIiwgb3BlcmF0aW9uLmZlZSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIm9sZCBvcGVyYXRpb24uZmVlXCIsIG9wZXJhdGlvbi5mZWUpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXRfaW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChvcGVyYXRpb24ucHJvcG9zZWRfb3BzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHkgPSAwOyB5IDwgb3BlcmF0aW9uLnByb3Bvc2VkX29wcy5sZW5ndGg7IHkrKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChzZXRfZmVlKG9wZXJhdGlvbi5wcm9wb3NlZF9vcHNbeV0ub3BbMV0pKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9cmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwOyBfaSA8IF90aGlzMy5vcGVyYXRpb25zLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0X2ZlZShfdGhpczMub3BlcmF0aW9uc1tfaV1bMV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgLy9ERUJVRyBjb25zb2xlLmxvZygnLi4uIGdldF9yZXF1aXJlZF9mZWVzJyxvcGVyYXRpb25zLGFzc2V0X2lkLGZsYXRfYXNzZXRzKVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJnZXRfcG90ZW50aWFsX3NpZ25hdHVyZXNcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldF9wb3RlbnRpYWxfc2lnbmF0dXJlcygpIHtcbiAgICAgICAgICAgIHZhciB0cl9vYmplY3QgPSBvcHMuc2lnbmVkX3RyYW5zYWN0aW9uLnRvT2JqZWN0KHRoaXMpO1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKFtBcGlzLmluc3RhbmNlKCkuZGJfYXBpKCkuZXhlYyhcImdldF9wb3RlbnRpYWxfc2lnbmF0dXJlc1wiLCBbdHJfb2JqZWN0XSksIEFwaXMuaW5zdGFuY2UoKS5kYl9hcGkoKS5leGVjKFwiZ2V0X3BvdGVudGlhbF9hZGRyZXNzX3NpZ25hdHVyZXNcIiwgW3RyX29iamVjdF0pXSkudGhlbihmdW5jdGlvbiAocmVzdWx0cykge1xuICAgICAgICAgICAgICAgIHJldHVybiB7IHB1YmtleXM6IHJlc3VsdHNbMF0sIGFkZHlzOiByZXN1bHRzWzFdIH07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImdldF9yZXF1aXJlZF9zaWduYXR1cmVzXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBnZXRfcmVxdWlyZWRfc2lnbmF0dXJlcyhhdmFpbGFibGVfa2V5cykge1xuICAgICAgICAgICAgaWYgKCFhdmFpbGFibGVfa2V5cy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKFtdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB0cl9vYmplY3QgPSBvcHMuc2lnbmVkX3RyYW5zYWN0aW9uLnRvT2JqZWN0KHRoaXMpO1xuICAgICAgICAgICAgLy9ERUJVRyBjb25zb2xlLmxvZygnLi4uIHRyX29iamVjdCcsdHJfb2JqZWN0KVxuICAgICAgICAgICAgcmV0dXJuIEFwaXMuaW5zdGFuY2UoKS5kYl9hcGkoKS5leGVjKFwiZ2V0X3JlcXVpcmVkX3NpZ25hdHVyZXNcIiwgW3RyX29iamVjdCwgYXZhaWxhYmxlX2tleXNdKS50aGVuKGZ1bmN0aW9uIChyZXF1aXJlZF9wdWJsaWNfa2V5cykge1xuICAgICAgICAgICAgICAgIC8vREVCVUcgY29uc29sZS5sb2coJy4uLiBnZXRfcmVxdWlyZWRfc2lnbmF0dXJlcycscmVxdWlyZWRfcHVibGljX2tleXMpXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlcXVpcmVkX3B1YmxpY19rZXlzO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJhZGRfc2lnbmVyXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBhZGRfc2lnbmVyKHByaXZhdGVfa2V5KSB7XG4gICAgICAgICAgICB2YXIgcHVibGljX2tleSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogcHJpdmF0ZV9rZXkudG9QdWJsaWNLZXkoKTtcblxuXG4gICAgICAgICAgICBhc3NlcnQocHJpdmF0ZV9rZXkuZCwgXCJyZXF1aXJlZCBQcml2YXRlS2V5IG9iamVjdFwiKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuc2lnbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYWxyZWFkeSBzaWduZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXB1YmxpY19rZXkuUSkge1xuICAgICAgICAgICAgICAgIHB1YmxpY19rZXkgPSBQdWJsaWNLZXkuZnJvbVB1YmxpY0tleVN0cmluZyhwdWJsaWNfa2V5KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIHByZXZlbnQgZHVwbGljYXRlc1xuICAgICAgICAgICAgdmFyIHNwSGV4ID0gcHJpdmF0ZV9rZXkudG9IZXgoKTtcbiAgICAgICAgICAgIHZhciBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMyA9IHRydWU7XG4gICAgICAgICAgICB2YXIgX2RpZEl0ZXJhdG9yRXJyb3IzID0gZmFsc2U7XG4gICAgICAgICAgICB2YXIgX2l0ZXJhdG9yRXJyb3IzID0gdW5kZWZpbmVkO1xuXG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIF9pdGVyYXRvcjMgPSB0aGlzLnNpZ25lcl9wcml2YXRlX2tleXNbU3ltYm9sLml0ZXJhdG9yXSgpLCBfc3RlcDM7ICEoX2l0ZXJhdG9yTm9ybWFsQ29tcGxldGlvbjMgPSAoX3N0ZXAzID0gX2l0ZXJhdG9yMy5uZXh0KCkpLmRvbmUpOyBfaXRlcmF0b3JOb3JtYWxDb21wbGV0aW9uMyA9IHRydWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHNwID0gX3N0ZXAzLnZhbHVlO1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChzcFswXS50b0hleCgpID09PSBzcEhleCkgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgIF9kaWRJdGVyYXRvckVycm9yMyA9IHRydWU7XG4gICAgICAgICAgICAgICAgX2l0ZXJhdG9yRXJyb3IzID0gZXJyO1xuICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIV9pdGVyYXRvck5vcm1hbENvbXBsZXRpb24zICYmIF9pdGVyYXRvcjMucmV0dXJuKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfaXRlcmF0b3IzLnJldHVybigpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBmaW5hbGx5IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKF9kaWRJdGVyYXRvckVycm9yMykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgX2l0ZXJhdG9yRXJyb3IzO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnNpZ25lcl9wcml2YXRlX2tleXMucHVzaChbcHJpdmF0ZV9rZXksIHB1YmxpY19rZXldKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcInNpZ25cIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNpZ24oKSB7XG4gICAgICAgICAgICB2YXIgY2hhaW5faWQgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IEFwaXMuaW5zdGFuY2UoKS5jaGFpbl9pZDtcblxuICAgICAgICAgICAgaWYgKCF0aGlzLnRyX2J1ZmZlcikge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIm5vdCBmaW5hbGl6ZWRcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodGhpcy5zaWduZWQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJhbHJlYWR5IHNpZ25lZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghdGhpcy5zaWduZXJfcHJpdmF0ZV9rZXlzLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlRyYW5zYWN0aW9uIHdhcyBub3Qgc2lnbmVkLiBEbyB5b3UgaGF2ZSBhIHByaXZhdGUga2V5PyBbbm9fc2lnbmVyc11cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZW5kID0gdGhpcy5zaWduZXJfcHJpdmF0ZV9rZXlzLmxlbmd0aDtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyAwIDwgZW5kID8gaSA8IGVuZCA6IGkgPiBlbmQ7IDAgPCBlbmQgPyBpKysgOiBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgX3NpZ25lcl9wcml2YXRlX2tleXMkID0gX3NsaWNlZFRvQXJyYXkodGhpcy5zaWduZXJfcHJpdmF0ZV9rZXlzW2ldLCAyKSxcbiAgICAgICAgICAgICAgICAgICAgcHJpdmF0ZV9rZXkgPSBfc2lnbmVyX3ByaXZhdGVfa2V5cyRbMF0sXG4gICAgICAgICAgICAgICAgICAgIHB1YmxpY19rZXkgPSBfc2lnbmVyX3ByaXZhdGVfa2V5cyRbMV07XG5cbiAgICAgICAgICAgICAgICB2YXIgc2lnID0gU2lnbmF0dXJlLnNpZ25CdWZmZXIoQnVmZmVyLmNvbmNhdChbbmV3IEJ1ZmZlcihjaGFpbl9pZCwgJ2hleCcpLCB0aGlzLnRyX2J1ZmZlcl0pLCBwcml2YXRlX2tleSwgcHVibGljX2tleSk7XG4gICAgICAgICAgICAgICAgdGhpcy5zaWduYXR1cmVzLnB1c2goc2lnLnRvQnVmZmVyKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhpcy5zaWduZXJfcHJpdmF0ZV9rZXlzID0gW107XG4gICAgICAgICAgICB0aGlzLnNpZ25lZCA9IHRydWU7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJzZXJpYWxpemVcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNlcmlhbGl6ZSgpIHtcbiAgICAgICAgICAgIHJldHVybiBvcHMuc2lnbmVkX3RyYW5zYWN0aW9uLnRvT2JqZWN0KHRoaXMpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6IFwidG9PYmplY3RcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvT2JqZWN0KCkge1xuICAgICAgICAgICAgcmV0dXJuIG9wcy5zaWduZWRfdHJhbnNhY3Rpb24udG9PYmplY3QodGhpcyk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJicm9hZGNhc3RcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGJyb2FkY2FzdCh3YXNfYnJvYWRjYXN0X2NhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgX3RoaXM0ID0gdGhpcztcblxuICAgICAgICAgICAgaWYgKHRoaXMudHJfYnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2Jyb2FkY2FzdCh3YXNfYnJvYWRjYXN0X2NhbGxiYWNrKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZmluYWxpemUoKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIF90aGlzNC5fYnJvYWRjYXN0KHdhc19icm9hZGNhc3RfY2FsbGJhY2spO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfV0pO1xuXG4gICAgcmV0dXJuIFRyYW5zYWN0aW9uQnVpbGRlcjtcbn0oKTtcblxudmFyIGJhc2VfZXhwaXJhdGlvbl9zZWMgPSBmdW5jdGlvbiBiYXNlX2V4cGlyYXRpb25fc2VjKCkge1xuICAgIHZhciBoZWFkX2Jsb2NrX3NlYyA9IE1hdGguY2VpbChnZXRIZWFkQmxvY2tEYXRlKCkuZ2V0VGltZSgpIC8gMTAwMCk7XG4gICAgdmFyIG5vd19zZWMgPSBNYXRoLmNlaWwoRGF0ZS5ub3coKSAvIDEwMDApO1xuICAgIC8vIFRoZSBoZWFkIGJsb2NrIHRpbWUgc2hvdWxkIGJlIHVwZGF0ZWQgZXZlcnkgMyBzZWNvbmRzLiAgSWYgaXQgaXNuJ3RcbiAgICAvLyB0aGVuIGhlbHAgdGhlIHRyYW5zYWN0aW9uIHRvIGV4cGlyZSAodXNlIGhlYWRfYmxvY2tfc2VjKVxuICAgIGlmIChub3dfc2VjIC0gaGVhZF9ibG9ja19zZWMgPiAzMCkge1xuICAgICAgICByZXR1cm4gaGVhZF9ibG9ja19zZWM7XG4gICAgfVxuICAgIC8vIElmIHRoZSB1c2VyJ3MgY2xvY2sgaXMgdmVyeSBmYXIgYmVoaW5kLCB1c2UgdGhlIGhlYWQgYmxvY2sgdGltZS5cbiAgICByZXR1cm4gTWF0aC5tYXgobm93X3NlYywgaGVhZF9ibG9ja19zZWMpO1xufTtcblxuZnVuY3Rpb24gX2Jyb2FkY2FzdCh3YXNfYnJvYWRjYXN0X2NhbGxiYWNrKSB7XG4gICAgdmFyIF90aGlzNSA9IHRoaXM7XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuXG4gICAgICAgIGlmICghX3RoaXM1LnNpZ25lZCkge1xuICAgICAgICAgICAgX3RoaXM1LnNpZ24oKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIV90aGlzNS50cl9idWZmZXIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIm5vdCBmaW5hbGl6ZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFfdGhpczUuc2lnbmF0dXJlcy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIm5vdCBzaWduZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFfdGhpczUub3BlcmF0aW9ucy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIm5vIG9wZXJhdGlvbnNcIik7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgdHJfb2JqZWN0ID0gb3BzLnNpZ25lZF90cmFuc2FjdGlvbi50b09iamVjdChfdGhpczUpO1xuICAgICAgICAvLyBjb25zb2xlLmxvZygnLi4uIGJyb2FkY2FzdF90cmFuc2FjdGlvbl93aXRoX2NhbGxiYWNrICEhIScpXG4gICAgICAgIEFwaXMuaW5zdGFuY2UoKS5uZXR3b3JrX2FwaSgpLmV4ZWMoXCJicm9hZGNhc3RfdHJhbnNhY3Rpb25fd2l0aF9jYWxsYmFja1wiLCBbZnVuY3Rpb24gKHJlcykge1xuICAgICAgICAgICAgcmV0dXJuIHJlc29sdmUocmVzKTtcbiAgICAgICAgfSwgdHJfb2JqZWN0XSkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAvL2NvbnNvbGUubG9nKCcuLi4gYnJvYWRjYXN0IHN1Y2Nlc3MsIHdhaXRpbmcgZm9yIGNhbGxiYWNrJylcbiAgICAgICAgICAgIGlmICh3YXNfYnJvYWRjYXN0X2NhbGxiYWNrKSB3YXNfYnJvYWRjYXN0X2NhbGxiYWNrKCk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgLy8gY29uc29sZS5sb2cgbWF5IGJlIHJlZHVuZGFudCBmb3IgbmV0d29yayBlcnJvcnMsIG90aGVyIGVycm9ycyBjb3VsZCBvY2N1clxuICAgICAgICAgICAgY29uc29sZS5sb2coZXJyb3IpO1xuICAgICAgICAgICAgdmFyIG1lc3NhZ2UgPSBlcnJvci5tZXNzYWdlO1xuICAgICAgICAgICAgaWYgKCFtZXNzYWdlKSB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IFwiXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZWplY3QobmV3IEVycm9yKG1lc3NhZ2UgKyBcIlxcblwiICsgJ2dyYXBoZW5lLWNyeXB0byAnICsgJyBkaWdlc3QgJyArIGhhc2guc2hhMjU2KF90aGlzNS50cl9idWZmZXIpLnRvU3RyaW5nKCdoZXgnKSArICcgdHJhbnNhY3Rpb24gJyArIF90aGlzNS50cl9idWZmZXIudG9TdHJpbmcoJ2hleCcpICsgJyAnICsgSlNPTi5zdHJpbmdpZnkodHJfb2JqZWN0KSkpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0pO1xufVxuXG5mdW5jdGlvbiBnZXRIZWFkQmxvY2tEYXRlKCkge1xuICAgIHJldHVybiB0aW1lU3RyaW5nVG9EYXRlKGhlYWRfYmxvY2tfdGltZV9zdHJpbmcpO1xufVxuXG5mdW5jdGlvbiB0aW1lU3RyaW5nVG9EYXRlKHRpbWVfc3RyaW5nKSB7XG4gICAgaWYgKCF0aW1lX3N0cmluZykgcmV0dXJuIG5ldyBEYXRlKFwiMTk3MC0wMS0wMVQwMDowMDowMC4wMDBaXCIpO1xuICAgIGlmICghL1okLy50ZXN0KHRpbWVfc3RyaW5nKSkgLy9kb2VzIG5vdCBlbmQgaW4gWlxuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vY3J5cHRvbm9tZXgvZ3JhcGhlbmUvaXNzdWVzLzM2OFxuICAgICAgICB0aW1lX3N0cmluZyA9IHRpbWVfc3RyaW5nICsgXCJaXCI7XG4gICAgcmV0dXJuIG5ldyBEYXRlKHRpbWVfc3RyaW5nKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBUcmFuc2FjdGlvbkJ1aWxkZXI7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbmZ1bmN0aW9uIGdldChzdGF0ZSkge1xuICAgIHJldHVybiBmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHJldHVybiBzdGF0ZVtrZXldIHx8IFwiXCI7XG4gICAgfTtcbn1cblxuZnVuY3Rpb24gc2V0KHN0YXRlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChrZXksIHZhbHVlKSB7XG4gICAgICAgIHN0YXRlW2tleV0gPSB2YWx1ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgZ2V0OiBnZXQsXG4gICAgc2V0OiBzZXRcbn07IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICAgIEFkZHJlc3M6IHJlcXVpcmUoXCIuL3NyYy9hZGRyZXNzXCIpLFxuICAgIEFlczogcmVxdWlyZShcIi4vc3JjL2Flc1wiKSxcbiAgICBQcml2YXRlS2V5OiByZXF1aXJlKFwiLi9zcmMvUHJpdmF0ZUtleVwiKSxcbiAgICBQdWJsaWNLZXk6IHJlcXVpcmUoXCIuL3NyYy9QdWJsaWNLZXlcIiksXG4gICAgU2lnbmF0dXJlOiByZXF1aXJlKFwiLi9zcmMvc2lnbmF0dXJlXCIpLFxuICAgIGJyYWluS2V5OiByZXF1aXJlKFwiLi9zcmMvQnJhaW5LZXlcIiksXG4gICAgaGFzaDogcmVxdWlyZShcIi4vc3JjL2hhc2hcIiksXG4gICAga2V5OiByZXF1aXJlKFwiLi9zcmMvS2V5VXRpbHNcIilcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG5vcm1hbGl6ZShicmFpbktleSkge1xuICAgIGlmICh0eXBlb2YgYnJhaW5LZXkgIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcInN0cmluZyByZXF1aXJlZCBmb3IgYnJhaW5LZXlcIik7XG4gICAgfVxuICAgIGJyYWluS2V5ID0gYnJhaW5LZXkudHJpbSgpO1xuICAgIHJldHVybiBicmFpbktleS5zcGxpdCgvW1xcdFxcblxcdlxcZlxcciBdKy8pLmpvaW4oJyAnKTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX3NsaWNlZFRvQXJyYXkgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIHNsaWNlSXRlcmF0b3IoYXJyLCBpKSB7IHZhciBfYXJyID0gW107IHZhciBfbiA9IHRydWU7IHZhciBfZCA9IGZhbHNlOyB2YXIgX2UgPSB1bmRlZmluZWQ7IHRyeSB7IGZvciAodmFyIF9pID0gYXJyW1N5bWJvbC5pdGVyYXRvcl0oKSwgX3M7ICEoX24gPSAoX3MgPSBfaS5uZXh0KCkpLmRvbmUpOyBfbiA9IHRydWUpIHsgX2Fyci5wdXNoKF9zLnZhbHVlKTsgaWYgKGkgJiYgX2Fyci5sZW5ndGggPT09IGkpIGJyZWFrOyB9IH0gY2F0Y2ggKGVycikgeyBfZCA9IHRydWU7IF9lID0gZXJyOyB9IGZpbmFsbHkgeyB0cnkgeyBpZiAoIV9uICYmIF9pW1wicmV0dXJuXCJdKSBfaVtcInJldHVyblwiXSgpOyB9IGZpbmFsbHkgeyBpZiAoX2QpIHRocm93IF9lOyB9IH0gcmV0dXJuIF9hcnI7IH0gcmV0dXJuIGZ1bmN0aW9uIChhcnIsIGkpIHsgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgeyByZXR1cm4gYXJyOyB9IGVsc2UgaWYgKFN5bWJvbC5pdGVyYXRvciBpbiBPYmplY3QoYXJyKSkgeyByZXR1cm4gc2xpY2VJdGVyYXRvcihhcnIsIGkpOyB9IGVsc2UgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiSW52YWxpZCBhdHRlbXB0IHRvIGRlc3RydWN0dXJlIG5vbi1pdGVyYWJsZSBpbnN0YW5jZVwiKTsgfSB9OyB9KCk7XG5cbnZhciBrZXk7XG52YXIgUHJpdmF0ZUtleSA9IHJlcXVpcmUoJy4vUHJpdmF0ZUtleScpO1xudmFyIFB1YmxpY0tleSA9IHJlcXVpcmUoJy4vUHVibGljS2V5Jyk7XG52YXIgQWRkcmVzcyA9IHJlcXVpcmUoJy4vYWRkcmVzcycpO1xudmFyIEFlcyA9IHJlcXVpcmUoJy4vYWVzJyk7XG5cbnZhciBoYXNoID0gcmVxdWlyZSgnLi9oYXNoJyk7XG4vLyB2YXIgZGljdGlvbmFyeSA9IHJlcXVpcmUoJy4vZGljdGlvbmFyeV9lbicpO1xudmFyIHNlY3VyZVJhbmRvbSA9IHJlcXVpcmUoJ3NlY3VyZS1yYW5kb20nKTtcblxudmFyIF9yZXF1aXJlID0gcmVxdWlyZSgncGVlcnBsYXlzanMtd3MnKSxcbiAgICBDaGFpbkNvbmZpZyA9IF9yZXF1aXJlLkNoYWluQ29uZmlnO1xuXG4vLyBoYXNoIGZvciAuMjUgc2Vjb25kXG5cblxudmFyIEhBU0hfUE9XRVJfTUlMTFMgPSAyNTA7XG5cbm1vZHVsZS5leHBvcnRzID0ga2V5ID0ge1xuXG4gICAgLyoqIFVzZXMgMSBzZWNvbmQgb2YgaGFzaGluZyBwb3dlciB0byBjcmVhdGUgYSBrZXkvcGFzc3dvcmQgY2hlY2tzdW0uICBBblxuICAgIGltcGxlbWVudGF0aW9uIGNhbiByZS1jYWxsIHRoaXMgbWV0aG9kIHdpdGggdGhlIHNhbWUgcGFzc3dvcmQgdG8gcmUtbWF0Y2hcbiAgICB0aGUgc3RyZW5ndGggb2YgdGhlIENQVSAoZWl0aGVyIGFmdGVyIG1vdmluZyBmcm9tIGEgZGVza3RvcCB0byBhIG1vYmlsZSxcbiAgICBtb2JpbGUgdG8gZGVza3RvcCwgb3IgTiB5ZWFycyBmcm9tIG5vdyB3aGVuIENQVXMgYXJlIHByZXN1bWFibHkgc3Ryb25nZXIpLlxuICAgICBBIHNhbHQgaXMgdXNlZCBmb3IgYWxsIHRoZSBub3JtYWwgcmVhc29ucy4uLlxuICAgICBAcmV0dXJuIG9iamVjdCB7XG4gICAgICAgIGFlc19wcml2YXRlOiBBZXMsXG4gICAgICAgIGNoZWNrc3VtOiBcIntoYXNoX2l0ZXJhdGlvbl9jb3VudH0se3NhbHR9LHtjaGVja3N1bX1cIlxuICAgIH1cbiAgICAqL1xuICAgIGFlc19jaGVja3N1bTogZnVuY3Rpb24gYWVzX2NoZWNrc3VtKHBhc3N3b3JkKSB7XG4gICAgICAgIGlmICghKHR5cGVvZiBwYXNzd29yZCA9PT0gXCJzdHJpbmdcIikpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBcInBhc3N3b3JkIHN0cmluZyByZXF1aXJlZFwiKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNhbHQgPSBzZWN1cmVSYW5kb20ucmFuZG9tQnVmZmVyKDQpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgICAgdmFyIGl0ZXJhdGlvbnMgPSAwO1xuICAgICAgICB2YXIgc2VjcmV0ID0gc2FsdCArIHBhc3N3b3JkO1xuICAgICAgICAvLyBoYXNoIGZvciAuMSBzZWNvbmRcbiAgICAgICAgdmFyIHN0YXJ0X3QgPSBEYXRlLm5vdygpO1xuICAgICAgICB3aGlsZSAoRGF0ZS5ub3coKSAtIHN0YXJ0X3QgPCBIQVNIX1BPV0VSX01JTExTKSB7XG4gICAgICAgICAgICBzZWNyZXQgPSBoYXNoLnNoYTI1NihzZWNyZXQpO1xuICAgICAgICAgICAgaXRlcmF0aW9ucyArPSAxO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIGNoZWNrc3VtID0gaGFzaC5zaGEyNTYoc2VjcmV0KTtcbiAgICAgICAgdmFyIGNoZWNrc3VtX3N0cmluZyA9IFtpdGVyYXRpb25zLCBzYWx0LnRvU3RyaW5nKCdoZXgnKSwgY2hlY2tzdW0uc2xpY2UoMCwgNCkudG9TdHJpbmcoJ2hleCcpXS5qb2luKCcsJyk7XG5cbiAgICAgICAgcmV0dXJuIHsgYWVzX3ByaXZhdGU6IEFlcy5mcm9tU2VlZChzZWNyZXQpLFxuICAgICAgICAgICAgY2hlY2tzdW06IGNoZWNrc3VtX3N0cmluZ1xuICAgICAgICB9O1xuICAgIH0sXG5cblxuICAgIC8qKiBQcm92aWRlIGEgbWF0Y2hpbmcgcGFzc3dvcmQgYW5kIGtleV9jaGVja3N1bS4gIEEgXCJ3cm9uZyBwYXNzd29yZFwiXG4gICAgZXJyb3IgaXMgdGhyb3duIGlmIHRoZSBwYXNzd29yZCBkb2VzIG5vdCBtYXRjaC4gIElmIHRoaXMgbWV0aG9kIHRha2VzXG4gICAgbXVjaCBtb3JlIG9yIGxlc3MgdGhhbiAxIHNlY29uZCB0byByZXR1cm4sIG9uZSBzaG91bGQgY29uc2lkZXIgdXBkYXRpbmdcbiAgICBhbGwgZW5jeXJwdGVkIGZpZWxkcyB1c2luZyBhIG5ldyBrZXkua2V5X2NoZWNrc3VtLlxuICAgICovXG4gICAgYWVzX3ByaXZhdGU6IGZ1bmN0aW9uIGFlc19wcml2YXRlKHBhc3N3b3JkLCBrZXlfY2hlY2tzdW0pIHtcbiAgICAgICAgdmFyIF9rZXlfY2hlY2tzdW0kc3BsaXQgPSBrZXlfY2hlY2tzdW0uc3BsaXQoJywnKSxcbiAgICAgICAgICAgIF9rZXlfY2hlY2tzdW0kc3BsaXQyID0gX3NsaWNlZFRvQXJyYXkoX2tleV9jaGVja3N1bSRzcGxpdCwgMyksXG4gICAgICAgICAgICBpdGVyYXRpb25zID0gX2tleV9jaGVja3N1bSRzcGxpdDJbMF0sXG4gICAgICAgICAgICBzYWx0ID0gX2tleV9jaGVja3N1bSRzcGxpdDJbMV0sXG4gICAgICAgICAgICBjaGVja3N1bSA9IF9rZXlfY2hlY2tzdW0kc3BsaXQyWzJdO1xuXG4gICAgICAgIHZhciBzZWNyZXQgPSBzYWx0ICsgcGFzc3dvcmQ7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyAwIDwgaXRlcmF0aW9ucyA/IGkgPCBpdGVyYXRpb25zIDogaSA+IGl0ZXJhdGlvbnM7IDAgPCBpdGVyYXRpb25zID8gaSsrIDogaSsrKSB7XG4gICAgICAgICAgICBzZWNyZXQgPSBoYXNoLnNoYTI1NihzZWNyZXQpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuZXdfY2hlY2tzdW0gPSBoYXNoLnNoYTI1NihzZWNyZXQpO1xuICAgICAgICBpZiAoIShuZXdfY2hlY2tzdW0uc2xpY2UoMCwgNCkudG9TdHJpbmcoJ2hleCcpID09PSBjaGVja3N1bSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIndyb25nIHBhc3N3b3JkXCIpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBBZXMuZnJvbVNlZWQoc2VjcmV0KTtcbiAgICB9LFxuXG5cbiAgICAvKipcbiAgICAgICAgQSB3ZWVrIHJhbmRvbSBudW1iZXIgZ2VuZXJhdG9yIGNhbiBydW4gb3V0IG9mIGVudHJvcHkuICBUaGlzIHNob3VsZCBlbnN1cmUgZXZlbiB0aGUgd29yc3QgcmFuZG9tIG51bWJlciBpbXBsZW1lbnRhdGlvbiB3aWxsIGJlIHJlYXNvbmFibHkgc2FmZS5cbiAgICAgICAgIEBwYXJhbTEgc3RyaW5nIGVudHJvcHkgb2YgYXQgbGVhc3QgMzIgYnl0ZXNcbiAgICAqL1xuICAgIHJhbmRvbTMyQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gcmFuZG9tMzJCeXRlQnVmZmVyKCkge1xuICAgICAgICB2YXIgZW50cm9weSA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogdGhpcy5icm93c2VyRW50cm9weSgpO1xuXG5cbiAgICAgICAgaWYgKCEodHlwZW9mIGVudHJvcHkgPT09ICdzdHJpbmcnKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwic3RyaW5nIHJlcXVpcmVkIGZvciBlbnRyb3B5XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGVudHJvcHkubGVuZ3RoIDwgMzIpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImV4cGVjdGluZyBhdCBsZWFzdCAzMiBieXRlcyBvZiBlbnRyb3B5XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0YXJ0X3QgPSBEYXRlLm5vdygpO1xuXG4gICAgICAgIHdoaWxlIChEYXRlLm5vdygpIC0gc3RhcnRfdCA8IEhBU0hfUE9XRVJfTUlMTFMpIHtcbiAgICAgICAgICAgIGVudHJvcHkgPSBoYXNoLnNoYTI1NihlbnRyb3B5KTtcbiAgICAgICAgfXZhciBoYXNoX2FycmF5ID0gW107XG4gICAgICAgIGhhc2hfYXJyYXkucHVzaChlbnRyb3B5KTtcblxuICAgICAgICAvLyBIYXNoaW5nIGZvciAxIHNlY29uZCBtYXkgaGVscHMgdGhlIGNvbXB1dGVyIGlzIG5vdCBsb3cgb24gZW50cm9weSAodGhpcyBtZXRob2QgbWF5IGJlIGNhbGxlZCBiYWNrLXRvLWJhY2spLlxuICAgICAgICBoYXNoX2FycmF5LnB1c2goc2VjdXJlUmFuZG9tLnJhbmRvbUJ1ZmZlcigzMikpO1xuXG4gICAgICAgIHJldHVybiBoYXNoLnNoYTI1NihCdWZmZXIuY29uY2F0KGhhc2hfYXJyYXkpKTtcbiAgICB9LFxuXG5cbiAgICBzdWdnZXN0X2JyYWluX2tleTogZnVuY3Rpb24gc3VnZ2VzdF9icmFpbl9rZXkoKSB7XG4gICAgICAgIHZhciBkaWN0aW9uYXJ5ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBcIixcIjtcbiAgICAgICAgdmFyIGVudHJvcHkgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHRoaXMuYnJvd3NlckVudHJvcHkoKTtcblxuXG4gICAgICAgIHZhciByYW5kb21CdWZmZXIgPSB0aGlzLnJhbmRvbTMyQnl0ZUJ1ZmZlcihlbnRyb3B5KTtcblxuICAgICAgICB2YXIgd29yZF9jb3VudCA9IDE2O1xuICAgICAgICB2YXIgZGljdGlvbmFyeV9saW5lcyA9IGRpY3Rpb25hcnkuc3BsaXQoJywnKTtcblxuICAgICAgICBpZiAoIShkaWN0aW9uYXJ5X2xpbmVzLmxlbmd0aCA9PT0gNDk3NDQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGVjdGluZyAnICsgNDk3NDQgKyAnIGJ1dCBnb3QgJyArIGRpY3Rpb25hcnlfbGluZXMubGVuZ3RoICsgJyBkaWN0aW9uYXJ5IHdvcmRzJyk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgYnJhaW5rZXkgPSBbXTtcbiAgICAgICAgdmFyIGVuZCA9IHdvcmRfY291bnQgKiAyO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZW5kOyBpICs9IDIpIHtcblxuICAgICAgICAgICAgLy8gcmFuZG9tQnVmZmVyIGhhcyAyNTYgYml0cyAvIDE2IGJpdHMgcGVyIHdvcmQgPT0gMTYgd29yZHNcbiAgICAgICAgICAgIHZhciBudW0gPSAocmFuZG9tQnVmZmVyW2ldIDw8IDgpICsgcmFuZG9tQnVmZmVyW2kgKyAxXTtcblxuICAgICAgICAgICAgLy8gY29udmVydCBpbnRvIGEgbnVtYmVyIGJldHdlZW4gMCBhbmQgMSAoaW5jbHVzaXZlKVxuICAgICAgICAgICAgdmFyIHJuZE11bHRpcGxpZXIgPSBudW0gLyBNYXRoLnBvdygyLCAxNik7XG4gICAgICAgICAgICB2YXIgd29yZEluZGV4ID0gTWF0aC5yb3VuZChkaWN0aW9uYXJ5X2xpbmVzLmxlbmd0aCAqIHJuZE11bHRpcGxpZXIpO1xuXG4gICAgICAgICAgICBicmFpbmtleS5wdXNoKGRpY3Rpb25hcnlfbGluZXNbd29yZEluZGV4XSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubm9ybWFsaXplX2JyYWluS2V5KGJyYWlua2V5LmpvaW4oJyAnKSk7XG4gICAgfSxcblxuICAgIGdldF9yYW5kb21fa2V5OiBmdW5jdGlvbiBnZXRfcmFuZG9tX2tleShlbnRyb3B5KSB7XG4gICAgICAgIHJldHVybiBQcml2YXRlS2V5LmZyb21CdWZmZXIodGhpcy5yYW5kb20zMkJ5dGVCdWZmZXIoZW50cm9weSkpO1xuICAgIH0sXG4gICAgZ2V0X2JyYWluUHJpdmF0ZUtleTogZnVuY3Rpb24gZ2V0X2JyYWluUHJpdmF0ZUtleShicmFpbktleSkge1xuICAgICAgICB2YXIgc2VxdWVuY2UgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IDA7XG5cbiAgICAgICAgaWYgKHNlcXVlbmNlIDwgMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiaW52YWxpZCBzZXF1ZW5jZVwiKTtcbiAgICAgICAgfVxuICAgICAgICBicmFpbktleSA9IGtleS5ub3JtYWxpemVfYnJhaW5LZXkoYnJhaW5LZXkpO1xuICAgICAgICByZXR1cm4gUHJpdmF0ZUtleS5mcm9tQnVmZmVyKGhhc2guc2hhMjU2KGhhc2guc2hhNTEyKGJyYWluS2V5ICsgXCIgXCIgKyBzZXF1ZW5jZSkpKTtcbiAgICB9LFxuXG5cbiAgICAvLyBUdXJuIGludmlzaWJsZSBzcGFjZSBsaWtlIGNoYXJhY3RlcnMgaW50byBhIHNpbmdsZSBzcGFjZVxuICAgIG5vcm1hbGl6ZV9icmFpbktleTogZnVuY3Rpb24gbm9ybWFsaXplX2JyYWluS2V5KGJyYWluS2V5KSB7XG4gICAgICAgIGlmICghKHR5cGVvZiBicmFpbktleSA9PT0gJ3N0cmluZycpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJzdHJpbmcgcmVxdWlyZWQgZm9yIGJyYWluS2V5XCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgYnJhaW5LZXkgPSBicmFpbktleS50cmltKCk7XG4gICAgICAgIHJldHVybiBicmFpbktleS5zcGxpdCgvW1xcdFxcblxcdlxcZlxcciBdKy8pLmpvaW4oJyAnKTtcbiAgICB9LFxuICAgIGJyb3dzZXJFbnRyb3B5OiBmdW5jdGlvbiBicm93c2VyRW50cm9weSgpIHtcblxuICAgICAgICB2YXIgZW50cm9weVN0ciA9IFwiXCI7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBlbnRyb3B5U3RyID0gbmV3IERhdGUoKS50b1N0cmluZygpICsgXCIgXCIgKyB3aW5kb3cuc2NyZWVuLmhlaWdodCArIFwiIFwiICsgd2luZG93LnNjcmVlbi53aWR0aCArIFwiIFwiICsgd2luZG93LnNjcmVlbi5jb2xvckRlcHRoICsgXCIgXCIgKyBcIiBcIiArIHdpbmRvdy5zY3JlZW4uYXZhaWxIZWlnaHQgKyBcIiBcIiArIHdpbmRvdy5zY3JlZW4uYXZhaWxXaWR0aCArIFwiIFwiICsgd2luZG93LnNjcmVlbi5waXhlbERlcHRoICsgbmF2aWdhdG9yLmxhbmd1YWdlICsgXCIgXCIgKyB3aW5kb3cubG9jYXRpb24gKyBcIiBcIiArIHdpbmRvdy5oaXN0b3J5Lmxlbmd0aDtcblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIG1pbWVUeXBlOyBpIDwgbmF2aWdhdG9yLm1pbWVUeXBlcy5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIG1pbWVUeXBlID0gbmF2aWdhdG9yLm1pbWVUeXBlc1tpXTtcbiAgICAgICAgICAgICAgICBlbnRyb3B5U3RyICs9IG1pbWVUeXBlLmRlc2NyaXB0aW9uICsgXCIgXCIgKyBtaW1lVHlwZS50eXBlICsgXCIgXCIgKyBtaW1lVHlwZS5zdWZmaXhlcyArIFwiIFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc29sZS5sb2coXCJJTkZPXFx0YnJvd3NlckVudHJvcHkgZ2F0aGVyZWRcIik7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAvL25vZGVqczpSZWZlcmVuY2VFcnJvcjogd2luZG93IGlzIG5vdCBkZWZpbmVkXG4gICAgICAgICAgICBlbnRyb3B5U3RyID0gaGFzaC5zaGEyNTYobmV3IERhdGUoKS50b1N0cmluZygpKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBiID0gbmV3IEJ1ZmZlcihlbnRyb3B5U3RyKTtcbiAgICAgICAgZW50cm9weVN0ciArPSBiLnRvU3RyaW5nKCdiaW5hcnknKSArIFwiIFwiICsgbmV3IERhdGUoKS50b1N0cmluZygpO1xuICAgICAgICByZXR1cm4gZW50cm9weVN0cjtcbiAgICB9LFxuXG5cbiAgICAvLyBAcmV0dXJuIGFycmF5IG9mIDUgbGVnYWN5IGFkZHJlc3NlcyBmb3IgYSBwdWJrZXkgc3RyaW5nIHBhcmFtZXRlci5cbiAgICBhZGRyZXNzZXM6IGZ1bmN0aW9uIGFkZHJlc3NlcyhwdWJrZXkpIHtcbiAgICAgICAgdmFyIGFkZHJlc3NfcHJlZml4ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBDaGFpbkNvbmZpZy5hZGRyZXNzX3ByZWZpeDtcblxuICAgICAgICB2YXIgcHVibGljX2tleSA9IFB1YmxpY0tleS5mcm9tUHVibGljS2V5U3RyaW5nKHB1YmtleSwgYWRkcmVzc19wcmVmaXgpO1xuICAgICAgICAvLyBTIEwgTyBXXG4gICAgICAgIHZhciBhZGRyZXNzX3N0cmluZyA9IFtBZGRyZXNzLmZyb21QdWJsaWMocHVibGljX2tleSwgZmFsc2UsIDApLnRvU3RyaW5nKGFkZHJlc3NfcHJlZml4KSwgLy8gYnRjX3VuY29tcHJlc3NlZFxuICAgICAgICBBZGRyZXNzLmZyb21QdWJsaWMocHVibGljX2tleSwgdHJ1ZSwgMCkudG9TdHJpbmcoYWRkcmVzc19wcmVmaXgpLCAvLyBidGNfY29tcHJlc3NlZFxuICAgICAgICBBZGRyZXNzLmZyb21QdWJsaWMocHVibGljX2tleSwgZmFsc2UsIDU2KS50b1N0cmluZyhhZGRyZXNzX3ByZWZpeCksIC8vIHB0c191bmNvbXByZXNzZWRcbiAgICAgICAgQWRkcmVzcy5mcm9tUHVibGljKHB1YmxpY19rZXksIHRydWUsIDU2KS50b1N0cmluZyhhZGRyZXNzX3ByZWZpeCksIC8vIHB0c19jb21wcmVzc2VkXG4gICAgICAgIHB1YmxpY19rZXkudG9BZGRyZXNzU3RyaW5nKGFkZHJlc3NfcHJlZml4KSAvLyBidHNfc2hvcnQsIG1vc3QgcmVjZW50IGZvcm1hdFxuICAgICAgICBdO1xuICAgICAgICByZXR1cm4gYWRkcmVzc19zdHJpbmc7XG4gICAgfVxufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBlY3VydmUgPSByZXF1aXJlKCdlY3VydmUnKTtcblxudmFyIF9yZXF1aXJlID0gcmVxdWlyZSgnZWN1cnZlJyksXG4gICAgUG9pbnQgPSBfcmVxdWlyZS5Qb2ludCxcbiAgICBnZXRDdXJ2ZUJ5TmFtZSA9IF9yZXF1aXJlLmdldEN1cnZlQnlOYW1lO1xuXG52YXIgc2VjcDI1NmsxID0gZ2V0Q3VydmVCeU5hbWUoJ3NlY3AyNTZrMScpO1xudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCdiaWdpJyk7XG5cbnZhciBfcmVxdWlyZTIgPSByZXF1aXJlKCdiczU4JyksXG4gICAgZW5jb2RlID0gX3JlcXVpcmUyLmVuY29kZSxcbiAgICBkZWNvZGUgPSBfcmVxdWlyZTIuZGVjb2RlO1xuXG52YXIgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0Jyk7XG52YXIgaGFzaCA9IHJlcXVpcmUoJy4vaGFzaCcpO1xudmFyIFB1YmxpY0tleSA9IHJlcXVpcmUoJy4vUHVibGljS2V5Jyk7XG52YXIgZGVlcEVxdWFsID0gcmVxdWlyZShcImRlZXAtZXF1YWxcIik7XG5cbnZhciBHID0gc2VjcDI1NmsxLkcsXG4gICAgbiA9IHNlY3AyNTZrMS5uO1xuXG52YXIgUHJpdmF0ZUtleSA9IGZ1bmN0aW9uICgpIHtcblxuICAgIC8qKlxuICAgICAgICBAcHJpdmF0ZSBzZWUgc3RhdGljIGZ1bmN0aW9uc1xuICAgICAgICBAcGFyYW0ge0JpZ0ludGVnZXJ9XG4gICAgKi9cbiAgICBmdW5jdGlvbiBQcml2YXRlS2V5KGQpIHtcbiAgICAgICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIFByaXZhdGVLZXkpO1xuXG4gICAgICAgIHRoaXMuZCA9IGQ7XG4gICAgfVxuXG4gICAgX2NyZWF0ZUNsYXNzKFByaXZhdGVLZXksIFt7XG4gICAgICAgIGtleTogJ3RvV2lmJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvV2lmKCkge1xuICAgICAgICAgICAgdmFyIHByaXZhdGVfa2V5ID0gdGhpcy50b0J1ZmZlcigpO1xuICAgICAgICAgICAgLy8gY2hlY2tzdW0gaW5jbHVkZXMgdGhlIHZlcnNpb25cbiAgICAgICAgICAgIHByaXZhdGVfa2V5ID0gQnVmZmVyLmNvbmNhdChbbmV3IEJ1ZmZlcihbMHg4MF0pLCBwcml2YXRlX2tleV0pO1xuICAgICAgICAgICAgdmFyIGNoZWNrc3VtID0gaGFzaC5zaGEyNTYocHJpdmF0ZV9rZXkpO1xuICAgICAgICAgICAgY2hlY2tzdW0gPSBoYXNoLnNoYTI1NihjaGVja3N1bSk7XG4gICAgICAgICAgICBjaGVja3N1bSA9IGNoZWNrc3VtLnNsaWNlKDAsIDQpO1xuICAgICAgICAgICAgdmFyIHByaXZhdGVfd2lmID0gQnVmZmVyLmNvbmNhdChbcHJpdmF0ZV9rZXksIGNoZWNrc3VtXSk7XG4gICAgICAgICAgICByZXR1cm4gZW5jb2RlKHByaXZhdGVfd2lmKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgICAgQHJldHVybiB7UG9pbnR9XG4gICAgICAgICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3RvUHVibGljS2V5UG9pbnQnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdG9QdWJsaWNLZXlQb2ludCgpIHtcbiAgICAgICAgICAgIHZhciBRO1xuICAgICAgICAgICAgcmV0dXJuIFEgPSBzZWNwMjU2azEuRy5tdWx0aXBseSh0aGlzLmQpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICd0b1B1YmxpY0tleScsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b1B1YmxpY0tleSgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnB1YmxpY19rZXkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5wdWJsaWNfa2V5O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHVibGljX2tleSA9IFB1YmxpY0tleS5mcm9tUG9pbnQodGhpcy50b1B1YmxpY0tleVBvaW50KCkpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICd0b0J1ZmZlcicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b0J1ZmZlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmQudG9CdWZmZXIoMzIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqIEVDSUVTICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2dldF9zaGFyZWRfc2VjcmV0JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGdldF9zaGFyZWRfc2VjcmV0KHB1YmxpY19rZXkpIHtcbiAgICAgICAgICAgIHZhciBsZWdhY3kgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IGZhbHNlO1xuXG4gICAgICAgICAgICBwdWJsaWNfa2V5ID0gdG9QdWJsaWMocHVibGljX2tleSk7XG4gICAgICAgICAgICB2YXIgS0IgPSBwdWJsaWNfa2V5LnRvVW5jb21wcmVzc2VkKCkudG9CdWZmZXIoKTtcbiAgICAgICAgICAgIHZhciBLQlAgPSBQb2ludC5mcm9tQWZmaW5lKHNlY3AyNTZrMSwgQmlnSW50ZWdlci5mcm9tQnVmZmVyKEtCLnNsaWNlKDEsIDMzKSksIC8vIHhcbiAgICAgICAgICAgIEJpZ0ludGVnZXIuZnJvbUJ1ZmZlcihLQi5zbGljZSgzMywgNjUpKSAvLyB5XG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdmFyIHIgPSB0aGlzLnRvQnVmZmVyKCk7XG4gICAgICAgICAgICB2YXIgUCA9IEtCUC5tdWx0aXBseShCaWdJbnRlZ2VyLmZyb21CdWZmZXIocikpO1xuICAgICAgICAgICAgdmFyIFMgPSBQLmFmZmluZVgudG9CdWZmZXIoeyBzaXplOiAzMiB9KTtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICB0aGUgaW5wdXQgdG8gc2hhNTEyIG11c3QgYmUgZXhhY3RseSAzMi1ieXRlcywgdG8gbWF0Y2ggdGhlIGMrKyBpbXBsZW1lbnRhdGlvblxuICAgICAgICAgICAgb2YgZ2V0X3NoYXJlZF9zZWNyZXQuICBSaWdodCBub3cgUyB3aWxsIGJlIHNob3J0ZXIgaWYgdGhlIG1vc3Qgc2lnbmlmaWNhbnRcbiAgICAgICAgICAgIGJ5dGUocykgaXMgemVyby4gIFBhZCBpdCBiYWNrIHRvIHRoZSBmdWxsIDMyLWJ5dGVzXG4gICAgICAgICAgICAqL1xuICAgICAgICAgICAgaWYgKCFsZWdhY3kgJiYgUy5sZW5ndGggPCAzMikge1xuICAgICAgICAgICAgICAgIHBhZCA9IG5ldyBCdWZmZXIoMzIgLSBTLmxlbmd0aCkuZmlsbCgwKTtcbiAgICAgICAgICAgICAgICBTID0gQnVmZmVyLmNvbmNhdChbcGFkLCBTXSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFNIQTUxMiB1c2VkIGluIEVDSUVTXG4gICAgICAgICAgICByZXR1cm4gaGFzaC5zaGE1MTIoUyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAvKiogRUNJRVMgKGRvZXMgbm90IGFsd2F5cyBtYXRjaCB0aGUgUG9pbnQuZnJvbUFmZmluZSB2ZXJzaW9uIGFib3ZlKSAqL1xuICAgICAgICAvLyBnZXRfc2hhcmVkX3NlY3JldChwdWJsaWNfa2V5KXtcbiAgICAgICAgLy8gICAgIHB1YmxpY19rZXkgPSB0b1B1YmxpYyhwdWJsaWNfa2V5KVxuICAgICAgICAvLyAgICAgdmFyIFAgPSBwdWJsaWNfa2V5LlEubXVsdGlwbHkoIHRoaXMuZCApO1xuICAgICAgICAvLyAgICAgdmFyIFMgPSBQLmFmZmluZVgudG9CdWZmZXIoe3NpemU6IDMyfSk7XG4gICAgICAgIC8vICAgICAvLyBFQ0lFUywgYWRkcyBhbiBleHRyYSBzaGE1MTJcbiAgICAgICAgLy8gICAgIHJldHVybiBoYXNoLnNoYTUxMihTKTtcbiAgICAgICAgLy8gfVxuXG4gICAgICAgIC8qKiBAdGhyb3dzIHtFcnJvcn0gLSBvdmVyZmxvdyBvZiB0aGUga2V5IGNvdWxkIG5vdCBiZSBkZXJpdmVkICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2NoaWxkJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGNoaWxkKG9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0ID0gQnVmZmVyLmNvbmNhdChbdGhpcy50b1B1YmxpY0tleSgpLnRvQnVmZmVyKCksIG9mZnNldF0pO1xuICAgICAgICAgICAgb2Zmc2V0ID0gaGFzaC5zaGEyNTYob2Zmc2V0KTtcbiAgICAgICAgICAgIHZhciBjID0gQmlnSW50ZWdlci5mcm9tQnVmZmVyKG9mZnNldCk7XG5cbiAgICAgICAgICAgIGlmIChjLmNvbXBhcmVUbyhuKSA+PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJDaGlsZCBvZmZzZXQgd2VudCBvdXQgb2YgYm91bmRzLCB0cnkgYWdhaW5cIik7XG5cbiAgICAgICAgICAgIHZhciBkZXJpdmVkID0gdGhpcy5kLmFkZChjKTsgLy8ubW9kKG4pXG5cbiAgICAgICAgICAgIGlmIChkZXJpdmVkLnNpZ251bSgpID09PSAwKSB0aHJvdyBuZXcgRXJyb3IoXCJDaGlsZCBvZmZzZXQgZGVyaXZlZCB0byBhbiBpbnZhbGlkIGtleSwgdHJ5IGFnYWluXCIpO1xuXG4gICAgICAgICAgICByZXR1cm4gbmV3IFByaXZhdGVLZXkoZGVyaXZlZCk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiA8aGVscGVyX2Z1bmN0aW9ucz4gKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndG9CeXRlQnVmZmVyJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvQnl0ZUJ1ZmZlcigpIHtcbiAgICAgICAgICAgIHZhciBiID0gbmV3IEJ5dGVCdWZmZXIoQnl0ZUJ1ZmZlci5ERUZBVUxUX0NBUEFDSVRZLCBCeXRlQnVmZmVyLkxJVFRMRV9FTkRJQU4pO1xuICAgICAgICAgICAgdGhpcy5hcHBlbmRCeXRlQnVmZmVyKGIpO1xuICAgICAgICAgICAgcmV0dXJuIGIuY29weSgwLCBiLm9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3RvSGV4JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvSGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9CdWZmZXIoKS50b1N0cmluZygnaGV4Jyk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiA8L2hlbHBlcl9mdW5jdGlvbnM+ICovXG5cbiAgICB9XSwgW3tcbiAgICAgICAga2V5OiAnZnJvbUJ1ZmZlcicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tQnVmZmVyKGJ1Zikge1xuICAgICAgICAgICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkV4cGVjdGluZyBwYXJhbXRlciB0byBiZSBhIEJ1ZmZlciB0eXBlXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKDMyICE9PSBidWYubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ1dBUk46IEV4cGVjdGluZyAzMiBieXRlcywgaW5zdGVhZCBnb3QgJyArIGJ1Zi5sZW5ndGggKyAnLCBzdGFjayB0cmFjZTonLCBuZXcgRXJyb3IoKS5zdGFjayk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYnVmLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkVtcHR5IGJ1ZmZlclwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBuZXcgUHJpdmF0ZUtleShCaWdJbnRlZ2VyLmZyb21CdWZmZXIoYnVmKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogQGFyZyB7c3RyaW5nfSBzZWVkIC0gYW55IGxlbmd0aCBzdHJpbmcuICBUaGlzIGlzIHByaXZhdGUsIHRoZSBzYW1lIHNlZWQgcHJvZHVjZXMgdGhlIHNhbWUgcHJpdmF0ZSBrZXkgZXZlcnkgdGltZS4gICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2Zyb21TZWVkJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21TZWVkKHNlZWQpIHtcbiAgICAgICAgICAgIC8vIGdlbmVyYXRlX3ByaXZhdGVfa2V5XG4gICAgICAgICAgICBpZiAoISh0eXBlb2Ygc2VlZCA9PT0gJ3N0cmluZycpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdzZWVkIG11c3QgYmUgb2YgdHlwZSBzdHJpbmcnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBQcml2YXRlS2V5LmZyb21CdWZmZXIoaGFzaC5zaGEyNTYoc2VlZCkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqIEByZXR1cm4ge3N0cmluZ30gV2FsbGV0IEltcG9ydCBGb3JtYXQgKHN0aWxsIGEgc2VjcmV0LCBOb3QgZW5jcnlwdGVkKSAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICdmcm9tV2lmJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21XaWYoX3ByaXZhdGVfd2lmKSB7XG4gICAgICAgICAgICB2YXIgcHJpdmF0ZV93aWYgPSBuZXcgQnVmZmVyKGRlY29kZShfcHJpdmF0ZV93aWYpKTtcbiAgICAgICAgICAgIHZhciB2ZXJzaW9uID0gcHJpdmF0ZV93aWYucmVhZFVJbnQ4KDApO1xuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKDB4ODAsIHZlcnNpb24sICdFeHBlY3RlZCB2ZXJzaW9uICcgKyAweDgwICsgJywgaW5zdGVhZCBnb3QgJyArIHZlcnNpb24pO1xuICAgICAgICAgICAgLy8gY2hlY2tzdW0gaW5jbHVkZXMgdGhlIHZlcnNpb25cbiAgICAgICAgICAgIHZhciBwcml2YXRlX2tleSA9IHByaXZhdGVfd2lmLnNsaWNlKDAsIC00KTtcbiAgICAgICAgICAgIHZhciBjaGVja3N1bSA9IHByaXZhdGVfd2lmLnNsaWNlKC00KTtcbiAgICAgICAgICAgIHZhciBuZXdfY2hlY2tzdW0gPSBoYXNoLnNoYTI1Nihwcml2YXRlX2tleSk7XG4gICAgICAgICAgICBuZXdfY2hlY2tzdW0gPSBoYXNoLnNoYTI1NihuZXdfY2hlY2tzdW0pO1xuICAgICAgICAgICAgbmV3X2NoZWNrc3VtID0gbmV3X2NoZWNrc3VtLnNsaWNlKDAsIDQpO1xuICAgICAgICAgICAgdmFyIGlzRXF1YWwgPSBkZWVwRXF1YWwoY2hlY2tzdW0sIG5ld19jaGVja3N1bSk7IC8vLCAnSW52YWxpZCBjaGVja3N1bSdcbiAgICAgICAgICAgIGlmICghaXNFcXVhbCkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkNoZWNrc3VtIGRpZCBub3QgbWF0Y2hcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBwcml2YXRlX2tleSA9IHByaXZhdGVfa2V5LnNsaWNlKDEpO1xuICAgICAgICAgICAgcHJpdmF0ZV9rZXkgPSBwcml2YXRlX2tleS5zbGljZSgwLCAzMik7XG4gICAgICAgICAgICByZXR1cm4gUHJpdmF0ZUtleS5mcm9tQnVmZmVyKHByaXZhdGVfa2V5KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnZnJvbUhleCcsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tSGV4KGhleCkge1xuICAgICAgICAgICAgcmV0dXJuIFByaXZhdGVLZXkuZnJvbUJ1ZmZlcihuZXcgQnVmZmVyKGhleCwgJ2hleCcpKTtcbiAgICAgICAgfVxuICAgIH1dKTtcblxuICAgIHJldHVybiBQcml2YXRlS2V5O1xufSgpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFByaXZhdGVLZXk7XG5cbnZhciB0b1B1YmxpYyA9IGZ1bmN0aW9uIHRvUHVibGljKGRhdGEpIHtcbiAgICByZXR1cm4gZGF0YSA9PSBudWxsID8gZGF0YSA6IGRhdGEuUSA/IGRhdGEgOiBQdWJsaWNLZXkuZnJvbVN0cmluZ09yVGhyb3coZGF0YSk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCdiaWdpJyk7XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoJ2VjdXJ2ZScpLFxuICAgIFBvaW50ID0gX3JlcXVpcmUuUG9pbnQsXG4gICAgZ2V0Q3VydmVCeU5hbWUgPSBfcmVxdWlyZS5nZXRDdXJ2ZUJ5TmFtZTtcblxudmFyIHNlY3AyNTZrMSA9IGdldEN1cnZlQnlOYW1lKCdzZWNwMjU2azEnKTtcblxudmFyIF9yZXF1aXJlMiA9IHJlcXVpcmUoJ2JzNTgnKSxcbiAgICBlbmNvZGUgPSBfcmVxdWlyZTIuZW5jb2RlLFxuICAgIGRlY29kZSA9IF9yZXF1aXJlMi5kZWNvZGU7XG5cbnZhciBoYXNoID0gcmVxdWlyZSgnLi9oYXNoJyk7XG5cbnZhciBfcmVxdWlyZTMgPSByZXF1aXJlKCdwZWVycGxheXNqcy13cycpLFxuICAgIENoYWluQ29uZmlnID0gX3JlcXVpcmUzLkNoYWluQ29uZmlnO1xuXG52YXIgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0Jyk7XG52YXIgZGVlcEVxdWFsID0gcmVxdWlyZShcImRlZXAtZXF1YWxcIik7XG5cbnZhciBHID0gc2VjcDI1NmsxLkcsXG4gICAgbiA9IHNlY3AyNTZrMS5uO1xuXG52YXIgUHVibGljS2V5ID0gZnVuY3Rpb24gKCkge1xuXG4gICAgLyoqIEBwYXJhbSB7UG9pbnR9IHB1YmxpYyBrZXkgKi9cbiAgICBmdW5jdGlvbiBQdWJsaWNLZXkoUSkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUHVibGljS2V5KTtcblxuICAgICAgICB0aGlzLlEgPSBRO1xuICAgIH1cblxuICAgIF9jcmVhdGVDbGFzcyhQdWJsaWNLZXksIFt7XG4gICAgICAgIGtleTogJ3RvQnVmZmVyJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvQnVmZmVyKCkge1xuICAgICAgICAgICAgdmFyIGNvbXByZXNzZWQgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHRoaXMuUSA/IHRoaXMuUS5jb21wcmVzc2VkIDogbnVsbDtcblxuICAgICAgICAgICAgaWYgKHRoaXMuUSA9PT0gbnVsbCkgcmV0dXJuIG5ldyBCdWZmZXIoJzAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMCcsICdoZXgnKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLlEuZ2V0RW5jb2RlZChjb21wcmVzc2VkKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndG9VbmNvbXByZXNzZWQnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdG9VbmNvbXByZXNzZWQoKSB7XG4gICAgICAgICAgICB2YXIgYnVmID0gdGhpcy5RLmdldEVuY29kZWQoZmFsc2UpO1xuICAgICAgICAgICAgdmFyIHBvaW50ID0gUG9pbnQuZGVjb2RlRnJvbShzZWNwMjU2azEsIGJ1Zik7XG4gICAgICAgICAgICByZXR1cm4gUHVibGljS2V5LmZyb21Qb2ludChwb2ludCk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogYnRzOjpibG9ja2NoYWluOjphZGRyZXNzICh1bmlxdWUgYnV0IG5vdCBhIGZ1bGwgcHVibGljIGtleSkgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndG9CbG9ja2NoYWluQWRkcmVzcycsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b0Jsb2NrY2hhaW5BZGRyZXNzKCkge1xuICAgICAgICAgICAgdmFyIHB1Yl9idWYgPSB0aGlzLnRvQnVmZmVyKCk7XG4gICAgICAgICAgICB2YXIgcHViX3NoYSA9IGhhc2guc2hhNTEyKHB1Yl9idWYpO1xuICAgICAgICAgICAgcmV0dXJuIGhhc2gucmlwZW1kMTYwKHB1Yl9zaGEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqIEFsaWFzIGZvciB7QGxpbmsgdG9QdWJsaWNLZXlTdHJpbmd9ICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3RvU3RyaW5nJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgdmFyIGFkZHJlc3NfcHJlZml4ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBDaGFpbkNvbmZpZy5hZGRyZXNzX3ByZWZpeDtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9QdWJsaWNLZXlTdHJpbmcoYWRkcmVzc19wcmVmaXgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAgICBGdWxsIHB1YmxpYyBrZXlcbiAgICAgICAgICAgIHtyZXR1cm59IHN0cmluZ1xuICAgICAgICAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICd0b1B1YmxpY0tleVN0cmluZycsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b1B1YmxpY0tleVN0cmluZygpIHtcbiAgICAgICAgICAgIHZhciBhZGRyZXNzX3ByZWZpeCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogQ2hhaW5Db25maWcuYWRkcmVzc19wcmVmaXg7XG5cbiAgICAgICAgICAgIHZhciBwdWJfYnVmID0gdGhpcy50b0J1ZmZlcigpO1xuICAgICAgICAgICAgdmFyIGNoZWNrc3VtID0gaGFzaC5yaXBlbWQxNjAocHViX2J1Zik7XG4gICAgICAgICAgICAvLyBTbGljZSBmcm9tIHRoZSBidWZmZXIgZGlyZWN0bHksIHNsaWNpbmcgZnJvbSB0aGUgY2hlY2tzdW0gVWludDhhcnJheSB3aWxsIHJldHVybiB0aGUgZW50aXJlIGFycmF5IGVhY2ggdGltZS5cbiAgICAgICAgICAgIHZhciBzbGljZWQgPSBuZXcgVWludDhBcnJheShjaGVja3N1bS5idWZmZXIuc2xpY2UoMCwgNCkpO1xuXG4gICAgICAgICAgICAvLyBjb25jYXQgb25seSBhY2NlcHRzIGJ1ZmZlcnMgc28gaW5pdGlhbGl6ZSB0aGUgc2xpY2VkIFVpbnQ4YXJyYXkgYXMgYSBCdWZmZXIuXG4gICAgICAgICAgICB2YXIgYWRkeSA9IEJ1ZmZlci5jb25jYXQoW3B1Yl9idWYsIEJ1ZmZlci5mcm9tKHNsaWNlZCldKTtcbiAgICAgICAgICAgIHJldHVybiBhZGRyZXNzX3ByZWZpeCArIGVuY29kZShhZGR5KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKlxuICAgICAgICAgICAgQGFyZyB7c3RyaW5nfSBwdWJsaWNfa2V5IC0gbGlrZSBHUEhYeXouLi5cbiAgICAgICAgICAgIEBhcmcge3N0cmluZ30gYWRkcmVzc19wcmVmaXggLSBsaWtlIEdQSFxuICAgICAgICAgICAgQHJldHVybiBQdWJsaWNLZXkgb3IgYG51bGxgIChpZiB0aGUgcHVibGljX2tleSBzdHJpbmcgaXMgaW52YWxpZClcbiAgICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndG9BZGRyZXNzU3RyaW5nJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvQWRkcmVzc1N0cmluZygpIHtcbiAgICAgICAgICAgIHZhciBhZGRyZXNzX3ByZWZpeCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogQ2hhaW5Db25maWcuYWRkcmVzc19wcmVmaXg7XG5cbiAgICAgICAgICAgIHZhciBwdWJfYnVmID0gdGhpcy50b0J1ZmZlcigpO1xuICAgICAgICAgICAgdmFyIHB1Yl9zaGEgPSBoYXNoLnNoYTUxMihwdWJfYnVmKTtcbiAgICAgICAgICAgIHZhciBhZGR5ID0gaGFzaC5yaXBlbWQxNjAocHViX3NoYSk7XG4gICAgICAgICAgICB2YXIgY2hlY2tzdW0gPSBoYXNoLnJpcGVtZDE2MChhZGR5KTtcbiAgICAgICAgICAgIGFkZHkgPSBCdWZmZXIuY29uY2F0KFthZGR5LCBjaGVja3N1bS5zbGljZSgwLCA0KV0pO1xuICAgICAgICAgICAgcmV0dXJuIGFkZHJlc3NfcHJlZml4ICsgZW5jb2RlKGFkZHkpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICd0b1B0c0FkZHknLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdG9QdHNBZGR5KCkge1xuICAgICAgICAgICAgdmFyIHB1Yl9idWYgPSB0aGlzLnRvQnVmZmVyKCk7XG4gICAgICAgICAgICB2YXIgcHViX3NoYSA9IGhhc2guc2hhMjU2KHB1Yl9idWYpO1xuICAgICAgICAgICAgdmFyIGFkZHkgPSBoYXNoLnJpcGVtZDE2MChwdWJfc2hhKTtcbiAgICAgICAgICAgIGFkZHkgPSBCdWZmZXIuY29uY2F0KFtuZXcgQnVmZmVyKFsweDM4XSksIGFkZHldKTsgLy92ZXJzaW9uIDU2KGRlY2ltYWwpXG5cbiAgICAgICAgICAgIHZhciBjaGVja3N1bSA9IGhhc2guc2hhMjU2KGFkZHkpO1xuICAgICAgICAgICAgY2hlY2tzdW0gPSBoYXNoLnNoYTI1NihjaGVja3N1bSk7XG5cbiAgICAgICAgICAgIGFkZHkgPSBCdWZmZXIuY29uY2F0KFthZGR5LCBjaGVja3N1bS5zbGljZSgwLCA0KV0pO1xuICAgICAgICAgICAgcmV0dXJuIGVuY29kZShhZGR5KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnY2hpbGQnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gY2hpbGQob2Zmc2V0KSB7XG5cbiAgICAgICAgICAgIGFzc2VydChCdWZmZXIuaXNCdWZmZXIob2Zmc2V0KSwgXCJCdWZmZXIgcmVxdWlyZWQ6IG9mZnNldFwiKTtcbiAgICAgICAgICAgIGFzc2VydC5lcXVhbChvZmZzZXQubGVuZ3RoLCAzMiwgXCJvZmZzZXQgbGVuZ3RoXCIpO1xuXG4gICAgICAgICAgICBvZmZzZXQgPSBCdWZmZXIuY29uY2F0KFt0aGlzLnRvQnVmZmVyKCksIG9mZnNldF0pO1xuICAgICAgICAgICAgb2Zmc2V0ID0gaGFzaC5zaGEyNTYob2Zmc2V0KTtcblxuICAgICAgICAgICAgdmFyIGMgPSBCaWdJbnRlZ2VyLmZyb21CdWZmZXIob2Zmc2V0KTtcblxuICAgICAgICAgICAgaWYgKGMuY29tcGFyZVRvKG4pID49IDApIHRocm93IG5ldyBFcnJvcihcIkNoaWxkIG9mZnNldCB3ZW50IG91dCBvZiBib3VuZHMsIHRyeSBhZ2FpblwiKTtcblxuICAgICAgICAgICAgdmFyIGNHID0gRy5tdWx0aXBseShjKTtcbiAgICAgICAgICAgIHZhciBRcHJpbWUgPSB0aGlzLlEuYWRkKGNHKTtcblxuICAgICAgICAgICAgaWYgKHNlY3AyNTZrMS5pc0luZmluaXR5KFFwcmltZSkpIHRocm93IG5ldyBFcnJvcihcIkNoaWxkIG9mZnNldCBkZXJpdmVkIHRvIGFuIGludmFsaWQga2V5LCB0cnkgYWdhaW5cIik7XG5cbiAgICAgICAgICAgIHJldHVybiBQdWJsaWNLZXkuZnJvbVBvaW50KFFwcmltZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiA8SEVYPiAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICd0b0J5dGVCdWZmZXInLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdG9CeXRlQnVmZmVyKCkge1xuICAgICAgICAgICAgdmFyIGIgPSBuZXcgQnl0ZUJ1ZmZlcihCeXRlQnVmZmVyLkRFRkFVTFRfQ0FQQUNJVFksIEJ5dGVCdWZmZXIuTElUVExFX0VORElBTik7XG4gICAgICAgICAgICB0aGlzLmFwcGVuZEJ5dGVCdWZmZXIoYik7XG4gICAgICAgICAgICByZXR1cm4gYi5jb3B5KDAsIGIub2Zmc2V0KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndG9IZXgnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdG9IZXgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b0J1ZmZlcigpLnRvU3RyaW5nKCdoZXgnKTtcbiAgICAgICAgfVxuICAgIH1dLCBbe1xuICAgICAgICBrZXk6ICdmcm9tQmluYXJ5JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21CaW5hcnkoYmluKSB7XG4gICAgICAgICAgICByZXR1cm4gUHVibGljS2V5LmZyb21CdWZmZXIobmV3IEJ1ZmZlcihiaW4sICdiaW5hcnknKSk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2Zyb21CdWZmZXInLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZnJvbUJ1ZmZlcihidWZmZXIpIHtcbiAgICAgICAgICAgIGlmIChidWZmZXIudG9TdHJpbmcoJ2hleCcpID09PSAnMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwJykgcmV0dXJuIG5ldyBQdWJsaWNLZXkobnVsbCk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFB1YmxpY0tleShQb2ludC5kZWNvZGVGcm9tKHNlY3AyNTZrMSwgYnVmZmVyKSk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2Zyb21Qb2ludCcsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tUG9pbnQocG9pbnQpIHtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUHVibGljS2V5KHBvaW50KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnZnJvbVB1YmxpY0tleVN0cmluZycsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tUHVibGljS2V5U3RyaW5nKHB1YmxpY19rZXkpIHtcbiAgICAgICAgICAgIHZhciBhZGRyZXNzX3ByZWZpeCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogQ2hhaW5Db25maWcuYWRkcmVzc19wcmVmaXg7XG5cbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFB1YmxpY0tleS5mcm9tU3RyaW5nT3JUaHJvdyhwdWJsaWNfa2V5LCBhZGRyZXNzX3ByZWZpeCk7XG4gICAgICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICAgIEBhcmcge3N0cmluZ30gcHVibGljX2tleSAtIGxpa2UgR1BIWHl6Li4uXG4gICAgICAgICAgICBAYXJnIHtzdHJpbmd9IGFkZHJlc3NfcHJlZml4IC0gbGlrZSBHUEhcbiAgICAgICAgICAgIEB0aHJvd3Mge0Vycm9yfSBpZiBwdWJsaWMga2V5IGlzIGludmFsaWRcbiAgICAgICAgICAgIEByZXR1cm4gUHVibGljS2V5XG4gICAgICAgICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2Zyb21TdHJpbmdPclRocm93JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21TdHJpbmdPclRocm93KHB1YmxpY19rZXkpIHtcbiAgICAgICAgICAgIHZhciBhZGRyZXNzX3ByZWZpeCA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogQ2hhaW5Db25maWcuYWRkcmVzc19wcmVmaXg7XG5cbiAgICAgICAgICAgIHZhciBwcmVmaXggPSBwdWJsaWNfa2V5LnNsaWNlKDAsIGFkZHJlc3NfcHJlZml4Lmxlbmd0aCk7XG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwoYWRkcmVzc19wcmVmaXgsIHByZWZpeCwgJ0V4cGVjdGluZyBrZXkgdG8gYmVnaW4gd2l0aCAnICsgYWRkcmVzc19wcmVmaXggKyAnLCBpbnN0ZWFkIGdvdCAnICsgcHJlZml4KTtcbiAgICAgICAgICAgIHB1YmxpY19rZXkgPSBwdWJsaWNfa2V5LnNsaWNlKGFkZHJlc3NfcHJlZml4Lmxlbmd0aCk7XG5cbiAgICAgICAgICAgIHB1YmxpY19rZXkgPSBuZXcgQnVmZmVyKGRlY29kZShwdWJsaWNfa2V5KSwgJ2JpbmFyeScpO1xuICAgICAgICAgICAgdmFyIGNoZWNrc3VtID0gcHVibGljX2tleS5zbGljZSgtNCk7XG4gICAgICAgICAgICBwdWJsaWNfa2V5ID0gcHVibGljX2tleS5zbGljZSgwLCAtNCk7XG4gICAgICAgICAgICB2YXIgbmV3X2NoZWNrc3VtID0gaGFzaC5yaXBlbWQxNjAocHVibGljX2tleSk7XG4gICAgICAgICAgICBuZXdfY2hlY2tzdW0gPSBuZXdfY2hlY2tzdW0uc2xpY2UoMCwgNCk7XG4gICAgICAgICAgICB2YXIgaXNFcXVhbCA9IGRlZXBFcXVhbChjaGVja3N1bSwgbmV3X2NoZWNrc3VtKTsgLy8sICdJbnZhbGlkIGNoZWNrc3VtJ1xuICAgICAgICAgICAgaWYgKCFpc0VxdWFsKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiQ2hlY2tzdW0gZGlkIG5vdCBtYXRjaFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBQdWJsaWNLZXkuZnJvbUJ1ZmZlcihwdWJsaWNfa2V5KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnZnJvbUhleCcsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tSGV4KGhleCkge1xuICAgICAgICAgICAgcmV0dXJuIFB1YmxpY0tleS5mcm9tQnVmZmVyKG5ldyBCdWZmZXIoaGV4LCAnaGV4JykpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdmcm9tUHVibGljS2V5U3RyaW5nSGV4JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21QdWJsaWNLZXlTdHJpbmdIZXgoaGV4KSB7XG4gICAgICAgICAgICByZXR1cm4gUHVibGljS2V5LmZyb21QdWJsaWNLZXlTdHJpbmcobmV3IEJ1ZmZlcihoZXgsICdoZXgnKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiA8L0hFWD4gKi9cblxuICAgIH1dKTtcblxuICAgIHJldHVybiBQdWJsaWNLZXk7XG59KCk7XG5cbm1vZHVsZS5leHBvcnRzID0gUHVibGljS2V5OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpO1xuXG52YXIgX3JlcXVpcmUgPSByZXF1aXJlKCdwZWVycGxheXNqcy13cycpLFxuICAgIENoYWluQ29uZmlnID0gX3JlcXVpcmUuQ2hhaW5Db25maWc7XG5cbnZhciBoYXNoID0gcmVxdWlyZSgnLi9oYXNoJyk7XG5cbnZhciBfcmVxdWlyZTIgPSByZXF1aXJlKCdiczU4JyksXG4gICAgZW5jb2RlID0gX3JlcXVpcmUyLmVuY29kZSxcbiAgICBkZWNvZGUgPSBfcmVxdWlyZTIuZGVjb2RlO1xuXG52YXIgZGVlcEVxdWFsID0gcmVxdWlyZShcImRlZXAtZXF1YWxcIik7XG5cbi8qKiBBZGRyZXNzZXMgYXJlIHNob3J0ZW5lZCBub24tcmV2ZXJzYWJsZSBoYXNoZXMgb2YgYSBwdWJsaWMga2V5LiAgVGhlIGZ1bGwgUHVibGljS2V5IGlzIHByZWZlcnJlZC5cbiAgICBAZGVwcmVjYXRlZFxuKi9cblxudmFyIEFkZHJlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQWRkcmVzcyhhZGR5KSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBBZGRyZXNzKTtcblxuICAgICAgICB0aGlzLmFkZHkgPSBhZGR5O1xuICAgIH1cblxuICAgIF9jcmVhdGVDbGFzcyhBZGRyZXNzLCBbe1xuICAgICAgICBrZXk6ICd0b0J1ZmZlcicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b0J1ZmZlcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZHk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3RvU3RyaW5nJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvU3RyaW5nKCkge1xuICAgICAgICAgICAgdmFyIGFkZHJlc3NfcHJlZml4ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiBDaGFpbkNvbmZpZy5hZGRyZXNzX3ByZWZpeDtcblxuICAgICAgICAgICAgdmFyIGNoZWNrc3VtID0gaGFzaC5yaXBlbWQxNjAodGhpcy5hZGR5KTtcbiAgICAgICAgICAgIHZhciBhZGR5ID0gQnVmZmVyLmNvbmNhdChbdGhpcy5hZGR5LCBjaGVja3N1bS5zbGljZSgwLCA0KV0pO1xuICAgICAgICAgICAgcmV0dXJuIGFkZHJlc3NfcHJlZml4ICsgZW5jb2RlKGFkZHkpO1xuICAgICAgICB9XG4gICAgfV0sIFt7XG4gICAgICAgIGtleTogJ2Zyb21CdWZmZXInLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZnJvbUJ1ZmZlcihidWZmZXIpIHtcbiAgICAgICAgICAgIHZhciBfaGFzaCA9IGhhc2guc2hhNTEyKGJ1ZmZlcik7XG4gICAgICAgICAgICB2YXIgYWRkeSA9IGhhc2gucmlwZW1kMTYwKF9oYXNoKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQWRkcmVzcyhhZGR5KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnZnJvbVN0cmluZycsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tU3RyaW5nKHN0cmluZykge1xuICAgICAgICAgICAgdmFyIGFkZHJlc3NfcHJlZml4ID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBDaGFpbkNvbmZpZy5hZGRyZXNzX3ByZWZpeDtcblxuICAgICAgICAgICAgdmFyIHByZWZpeCA9IHN0cmluZy5zbGljZSgwLCBhZGRyZXNzX3ByZWZpeC5sZW5ndGgpO1xuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGFkZHJlc3NfcHJlZml4LCBwcmVmaXgsICdFeHBlY3Rpbmcga2V5IHRvIGJlZ2luIHdpdGggJyArIGFkZHJlc3NfcHJlZml4ICsgJywgaW5zdGVhZCBnb3QgJyArIHByZWZpeCk7XG4gICAgICAgICAgICB2YXIgYWRkeSA9IHN0cmluZy5zbGljZShhZGRyZXNzX3ByZWZpeC5sZW5ndGgpO1xuICAgICAgICAgICAgYWRkeSA9IG5ldyBCdWZmZXIoZGVjb2RlKGFkZHkpLCAnYmluYXJ5Jyk7XG4gICAgICAgICAgICB2YXIgY2hlY2tzdW0gPSBhZGR5LnNsaWNlKC00KTtcbiAgICAgICAgICAgIGFkZHkgPSBhZGR5LnNsaWNlKDAsIC00KTtcbiAgICAgICAgICAgIHZhciBuZXdfY2hlY2tzdW0gPSBoYXNoLnJpcGVtZDE2MChhZGR5KTtcbiAgICAgICAgICAgIG5ld19jaGVja3N1bSA9IG5ld19jaGVja3N1bS5zbGljZSgwLCA0KTtcbiAgICAgICAgICAgIHZhciBpc0VxdWFsID0gZGVlcEVxdWFsKGNoZWNrc3VtLCBuZXdfY2hlY2tzdW0pOyAvLywgJ0ludmFsaWQgY2hlY2tzdW0nXG4gICAgICAgICAgICBpZiAoIWlzRXF1YWwpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDaGVja3N1bSBkaWQgbm90IG1hdGNoXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIG5ldyBBZGRyZXNzKGFkZHkpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdmcm9tUHVibGljJyxcblxuXG4gICAgICAgIC8qKiBAcmV0dXJuIEFkZHJlc3MgLSBDb21wcmVzc2VkIFBUUyBmb3JtYXQgKGJ5IGRlZmF1bHQpICovXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tUHVibGljKHB1YmxpY19rZXkpIHtcbiAgICAgICAgICAgIHZhciBjb21wcmVzc2VkID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB0cnVlO1xuICAgICAgICAgICAgdmFyIHZlcnNpb24gPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IDU2O1xuXG4gICAgICAgICAgICB2YXIgc2hhMiA9IGhhc2guc2hhMjU2KHB1YmxpY19rZXkudG9CdWZmZXIoY29tcHJlc3NlZCkpO1xuICAgICAgICAgICAgdmFyIHJlcCA9IGhhc2gucmlwZW1kMTYwKHNoYTIpO1xuICAgICAgICAgICAgdmFyIHZlcnNpb25CdWZmZXIgPSBuZXcgQnVmZmVyKDEpO1xuICAgICAgICAgICAgdmVyc2lvbkJ1ZmZlci53cml0ZVVJbnQ4KDB4RkYgJiB2ZXJzaW9uLCAwKTtcbiAgICAgICAgICAgIHZhciBhZGRyID0gQnVmZmVyLmNvbmNhdChbdmVyc2lvbkJ1ZmZlciwgcmVwXSk7XG4gICAgICAgICAgICB2YXIgY2hlY2sgPSBoYXNoLnNoYTI1NihhZGRyKTtcbiAgICAgICAgICAgIGNoZWNrID0gaGFzaC5zaGEyNTYoY2hlY2spO1xuICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW2FkZHIsIGNoZWNrLnNsaWNlKDAsIDQpXSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEFkZHJlc3MoaGFzaC5yaXBlbWQxNjAoYnVmZmVyKSk7XG4gICAgICAgIH1cbiAgICB9XSk7XG5cbiAgICByZXR1cm4gQWRkcmVzcztcbn0oKTtcblxubW9kdWxlLmV4cG9ydHMgPSBBZGRyZXNzOyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG4vLyBodHRwczovL2NvZGUuZ29vZ2xlLmNvbS9wL2NyeXB0by1qc1xudmFyIEFFUyA9IHJlcXVpcmUoXCJjcnlwdG8tanMvYWVzXCIpO1xudmFyIGVuY0hleCA9IHJlcXVpcmUoXCJjcnlwdG8tanMvZW5jLWhleFwiKTtcbnZhciBlbmNCYXNlNjQgPSByZXF1aXJlKFwiY3J5cHRvLWpzL2VuYy1iYXNlNjRcIik7XG52YXIgYXNzZXJ0ID0gcmVxdWlyZShcImFzc2VydFwiKTtcblxudmFyIF9yZXF1aXJlID0gcmVxdWlyZShcImJ5dGVidWZmZXJcIiksXG4gICAgTG9uZyA9IF9yZXF1aXJlLkxvbmc7XG5cbnZhciBoYXNoID0gcmVxdWlyZSgnLi9oYXNoJyk7XG5cbi8qKiBQcm92aWRlcyBzeW1ldHJpYyBlbmNyeXB0IGFuZCBkZWNyeXB0IHZpYSBBRVMuICovXG5cbnZhciBBZXMgPSBmdW5jdGlvbiAoKSB7XG5cbiAgICAvKiogQHByaXZhdGUgKi9cbiAgICBmdW5jdGlvbiBBZXMoaXYsIGtleSkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQWVzKTtcblxuICAgICAgICB0aGlzLml2ID0gaXYsIHRoaXMua2V5ID0ga2V5O1xuICAgIH1cblxuICAgIC8qKiBUaGlzIGlzIGFuIGV4Y2VsbGVudCB3YXkgdG8gZW5zdXJlIHRoYXQgYWxsIHJlZmVyZW5jZXMgdG8gQWVzIGNhbiBub3Qgb3BlcmF0ZSBhbnltb3JlIChleGFtcGxlOiBhIHdhbGxldCBiZWNvbWVzIGxvY2tlZCkuICBBbiBhcHBsaWNhdGlvbiBzaG91bGQgZW5zdXJlIHRoZXJlIGlzIG9ubHkgb25lIEFlcyBvYmplY3QgaW5zdGFuY2UgZm9yIGEgZ2l2ZW4gc2VjcmV0IGBzZWVkYC4gKi9cblxuXG4gICAgX2NyZWF0ZUNsYXNzKEFlcywgW3tcbiAgICAgICAga2V5OiBcImNsZWFyXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBjbGVhcigpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLml2ID0gdGhpcy5rZXkgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogQGFyZyB7c3RyaW5nfSBzZWVkIC0gc2VjcmV0IHNlZWQgbWF5IGJlIHVzZWQgdG8gZW5jcnlwdCBvciBkZWNyeXB0LiAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6IFwiX2RlY3J5cHRfd29yZF9hcnJheVwiLFxuXG5cbiAgICAgICAgLyoqIEBwcml2YXRlICovXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBfZGVjcnlwdF93b3JkX2FycmF5KGNpcGhlcikge1xuICAgICAgICAgICAgLy8gaHR0cHM6Ly9jb2RlLmdvb2dsZS5jb20vcC9jcnlwdG8tanMvI0N1c3RvbV9LZXlfYW5kX0lWXG4gICAgICAgICAgICAvLyBzZWUgd2FsbGV0X3JlY29yZHMuY3BwIG1hc3Rlcl9rZXk6OmRlY3J5cHRfa2V5XG4gICAgICAgICAgICByZXR1cm4gQUVTLmRlY3J5cHQoeyBjaXBoZXJ0ZXh0OiBjaXBoZXIsIHNhbHQ6IG51bGwgfSwgdGhpcy5rZXksIHsgaXY6IHRoaXMuaXYgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogQHByaXZhdGUgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcIl9lbmNyeXB0X3dvcmRfYXJyYXlcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIF9lbmNyeXB0X3dvcmRfYXJyYXkocGxhaW50ZXh0KSB7XG4gICAgICAgICAgICAvL2h0dHBzOi8vY29kZS5nb29nbGUuY29tL3AvY3J5cHRvLWpzL2lzc3Vlcy9kZXRhaWw/aWQ9ODVcbiAgICAgICAgICAgIHZhciBjaXBoZXIgPSBBRVMuZW5jcnlwdChwbGFpbnRleHQsIHRoaXMua2V5LCB7IGl2OiB0aGlzLml2IH0pO1xuICAgICAgICAgICAgcmV0dXJuIGVuY0Jhc2U2NC5wYXJzZShjaXBoZXIudG9TdHJpbmcoKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogVGhpcyBtZXRob2QgZG9lcyBub3QgdXNlIGEgY2hlY2tzdW0sIHRoZSByZXR1cm5lZCBkYXRhIG11c3QgYmUgdmFsaWRhdGVkIHNvbWUgb3RoZXIgd2F5LlxuICAgICAgICAgICAgQGFyZyB7c3RyaW5nfSBjaXBoZXJ0ZXh0XG4gICAgICAgICAgICBAcmV0dXJuIHtCdWZmZXJ9IGJpbmFyeVxuICAgICAgICAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6IFwiZGVjcnlwdFwiLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZGVjcnlwdChjaXBoZXJ0ZXh0KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGNpcGhlcnRleHQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBjaXBoZXJ0ZXh0ID0gbmV3IEJ1ZmZlcihjaXBoZXJ0ZXh0LCAnYmluYXJ5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihjaXBoZXJ0ZXh0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImJ1ZmZlciByZXF1aXJlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzc2VydChjaXBoZXJ0ZXh0LCBcIk1pc3NpbmcgY2lwaGVyIHRleHRcIik7XG4gICAgICAgICAgICAvLyBoZXggaXMgdGhlIG9ubHkgY29tbW9uIGZvcm1hdFxuICAgICAgICAgICAgdmFyIGhleCA9IHRoaXMuZGVjcnlwdEhleChjaXBoZXJ0ZXh0LnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJ1ZmZlcihoZXgsICdoZXgnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBUaGlzIG1ldGhvZCBkb2VzIG5vdCB1c2UgYSBjaGVja3N1bSwgdGhlIHJldHVybmVkIGRhdGEgbXVzdCBiZSB2YWxpZGF0ZWQgc29tZSBvdGhlciB3YXkuXG4gICAgICAgICAgICBAYXJnIHtzdHJpbmd9IHBsYWludGV4dFxuICAgICAgICAgICAgQHJldHVybiB7QnVmZmVyfSBiaW5hcnlcbiAgICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImVuY3J5cHRcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGVuY3J5cHQocGxhaW50ZXh0KSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHBsYWludGV4dCA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgICAgIHBsYWludGV4dCA9IG5ldyBCdWZmZXIocGxhaW50ZXh0LCAnYmluYXJ5Jyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihwbGFpbnRleHQpKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiYnVmZmVyIHJlcXVpcmVkXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy9hc3NlcnQgcGxhaW50ZXh0LCBcIk1pc3NpbmcgcGxhaW4gdGV4dFwiXG4gICAgICAgICAgICAvLyBoZXggaXMgdGhlIG9ubHkgY29tbW9uIGZvcm1hdFxuICAgICAgICAgICAgdmFyIGhleCA9IHRoaXMuZW5jcnlwdEhleChwbGFpbnRleHQudG9TdHJpbmcoJ2hleCcpKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQnVmZmVyKGhleCwgJ2hleCcpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqIFRoaXMgbWV0aG9kIGRvZXMgbm90IHVzZSBhIGNoZWNrc3VtLCB0aGUgcmV0dXJuZWQgZGF0YSBtdXN0IGJlIHZhbGlkYXRlZCBzb21lIG90aGVyIHdheS5cbiAgICAgICAgICAgIEBhcmcge3N0cmluZ3xCdWZmZXJ9IHBsYWludGV4dFxuICAgICAgICAgICAgQHJldHVybiB7c3RyaW5nfSBoZXhcbiAgICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImVuY3J5cHRUb0hleFwiLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZW5jcnlwdFRvSGV4KHBsYWludGV4dCkge1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBwbGFpbnRleHQgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICBwbGFpbnRleHQgPSBuZXcgQnVmZmVyKHBsYWludGV4dCwgJ2JpbmFyeScpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIocGxhaW50ZXh0KSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImJ1ZmZlciByZXF1aXJlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vYXNzZXJ0IHBsYWludGV4dCwgXCJNaXNzaW5nIHBsYWluIHRleHRcIlxuICAgICAgICAgICAgLy8gaGV4IGlzIHRoZSBvbmx5IGNvbW1vbiBmb3JtYXRcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmVuY3J5cHRIZXgocGxhaW50ZXh0LnRvU3RyaW5nKCdoZXgnKSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogVGhpcyBtZXRob2QgZG9lcyBub3QgdXNlIGEgY2hlY2tzdW0sIHRoZSByZXR1cm5lZCBkYXRhIG11c3QgYmUgdmFsaWRhdGVkIHNvbWUgb3RoZXIgd2F5LlxuICAgICAgICAgICAgQGFyZyB7c3RyaW5nfSBjaXBoZXIgLSBoZXhcbiAgICAgICAgICAgIEByZXR1cm4ge3N0cmluZ30gYmluYXJ5IChjb3VsZCBlYXNpbHkgYmUgcmVhZGFibGUgdGV4dClcbiAgICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImRlY3J5cHRIZXhcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGRlY3J5cHRIZXgoY2lwaGVyKSB7XG4gICAgICAgICAgICBhc3NlcnQoY2lwaGVyLCBcIk1pc3NpbmcgY2lwaGVyIHRleHRcIik7XG4gICAgICAgICAgICAvLyBDb252ZXJ0IGRhdGEgaW50byB3b3JkIGFycmF5cyAodXNlZCBieSBDcnlwdG8pXG4gICAgICAgICAgICB2YXIgY2lwaGVyX2FycmF5ID0gZW5jSGV4LnBhcnNlKGNpcGhlcik7XG4gICAgICAgICAgICB2YXIgcGxhaW53b3JkcyA9IHRoaXMuX2RlY3J5cHRfd29yZF9hcnJheShjaXBoZXJfYXJyYXkpO1xuICAgICAgICAgICAgcmV0dXJuIGVuY0hleC5zdHJpbmdpZnkocGxhaW53b3Jkcyk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogVGhpcyBtZXRob2QgZG9lcyBub3QgdXNlIGEgY2hlY2tzdW0sIHRoZSByZXR1cm5lZCBkYXRhIG11c3QgYmUgdmFsaWRhdGVkIHNvbWUgb3RoZXIgd2F5LlxuICAgICAgICAgICAgQGFyZyB7c3RyaW5nfSBjaXBoZXIgLSBoZXhcbiAgICAgICAgICAgIEByZXR1cm4ge0J1ZmZlcn0gZW5jb2RlZCBhcyBzcGVjaWZpZWQgYnkgdGhlIHBhcmFtZXRlclxuICAgICAgICAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6IFwiZGVjcnlwdEhleFRvQnVmZmVyXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBkZWNyeXB0SGV4VG9CdWZmZXIoY2lwaGVyKSB7XG4gICAgICAgICAgICBhc3NlcnQoY2lwaGVyLCBcIk1pc3NpbmcgY2lwaGVyIHRleHRcIik7XG4gICAgICAgICAgICAvLyBDb252ZXJ0IGRhdGEgaW50byB3b3JkIGFycmF5cyAodXNlZCBieSBDcnlwdG8pXG4gICAgICAgICAgICB2YXIgY2lwaGVyX2FycmF5ID0gZW5jSGV4LnBhcnNlKGNpcGhlcik7XG4gICAgICAgICAgICB2YXIgcGxhaW53b3JkcyA9IHRoaXMuX2RlY3J5cHRfd29yZF9hcnJheShjaXBoZXJfYXJyYXkpO1xuICAgICAgICAgICAgdmFyIHBsYWluaGV4ID0gZW5jSGV4LnN0cmluZ2lmeShwbGFpbndvcmRzKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgQnVmZmVyKHBsYWluaGV4LCAnaGV4Jyk7XG4gICAgICAgIH1cblxuICAgICAgICAvKiogVGhpcyBtZXRob2QgZG9lcyBub3QgdXNlIGEgY2hlY2tzdW0sIHRoZSByZXR1cm5lZCBkYXRhIG11c3QgYmUgdmFsaWRhdGVkIHNvbWUgb3RoZXIgd2F5LlxuICAgICAgICAgICAgQGFyZyB7c3RyaW5nfSBjaXBoZXIgLSBoZXhcbiAgICAgICAgICAgIEBhcmcge3N0cmluZ30gW2VuY29kaW5nID0gJ2JpbmFyeSddIC0gYSB2YWxpZCBCdWZmZXIgZW5jb2RpbmdcbiAgICAgICAgICAgIEByZXR1cm4ge1N0cmluZ30gZW5jb2RlZCBhcyBzcGVjaWZpZWQgYnkgdGhlIHBhcmFtZXRlclxuICAgICAgICAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6IFwiZGVjcnlwdEhleFRvVGV4dFwiLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZGVjcnlwdEhleFRvVGV4dChjaXBoZXIpIHtcbiAgICAgICAgICAgIHZhciBlbmNvZGluZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogJ2JpbmFyeSc7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLmRlY3J5cHRIZXhUb0J1ZmZlcihjaXBoZXIpLnRvU3RyaW5nKGVuY29kaW5nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBUaGlzIG1ldGhvZCBkb2VzIG5vdCB1c2UgYSBjaGVja3N1bSwgdGhlIHJldHVybmVkIGRhdGEgbXVzdCBiZSB2YWxpZGF0ZWQgc29tZSBvdGhlciB3YXkuXG4gICAgICAgICAgICBAYXJnIHtzdHJpbmd9IHBsYWluaGV4IC0gaGV4IGZvcm1hdFxuICAgICAgICAgICAgQHJldHVybiB7U3RyaW5nfSBoZXhcbiAgICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImVuY3J5cHRIZXhcIixcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGVuY3J5cHRIZXgocGxhaW5oZXgpIHtcbiAgICAgICAgICAgIHZhciBwbGFpbl9hcnJheSA9IGVuY0hleC5wYXJzZShwbGFpbmhleCk7XG4gICAgICAgICAgICB2YXIgY2lwaGVyX2FycmF5ID0gdGhpcy5fZW5jcnlwdF93b3JkX2FycmF5KHBsYWluX2FycmF5KTtcbiAgICAgICAgICAgIHJldHVybiBlbmNIZXguc3RyaW5naWZ5KGNpcGhlcl9hcnJheSk7XG4gICAgICAgIH1cbiAgICB9XSwgW3tcbiAgICAgICAga2V5OiBcImZyb21TZWVkXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tU2VlZChzZWVkKSB7XG4gICAgICAgICAgICBpZiAoc2VlZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwic2VlZCBpcyByZXF1aXJlZFwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBfaGFzaCA9IGhhc2guc2hhNTEyKHNlZWQpO1xuICAgICAgICAgICAgX2hhc2ggPSBfaGFzaC50b1N0cmluZygnaGV4Jyk7XG4gICAgICAgICAgICAvLyBERUJVRyBjb25zb2xlLmxvZygnLi4uIGZyb21TZWVkIF9oYXNoJyxfaGFzaClcbiAgICAgICAgICAgIHJldHVybiBBZXMuZnJvbVNoYTUxMihfaGFzaCk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJmcm9tU2hhNTEyXCIsXG5cblxuICAgICAgICAvKiogQGFyZyB7c3RyaW5nfSBoYXNoIC0gQSAxMjggYnl0ZSBoZXggc3RyaW5nLCB0eXBpY2FsbHkgb25lIHdvdWxkIGNhbGwge0BsaW5rIGZyb21TZWVkfSBpbnN0ZWFkLiAqL1xuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZnJvbVNoYTUxMihoYXNoKSB7XG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwoaGFzaC5sZW5ndGgsIDEyOCwgXCJBIFNoYTUxMiBpbiBIRVggc2hvdWxkIGJlIDEyOCBjaGFyYWN0ZXJzIGxvbmcsIGluc3RlYWQgZ290IFwiICsgaGFzaC5sZW5ndGgpO1xuICAgICAgICAgICAgdmFyIGl2ID0gZW5jSGV4LnBhcnNlKGhhc2guc3Vic3RyaW5nKDY0LCA5NikpO1xuICAgICAgICAgICAgdmFyIGtleSA9IGVuY0hleC5wYXJzZShoYXNoLnN1YnN0cmluZygwLCA2NCkpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBBZXMoaXYsIGtleSk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogXCJmcm9tQnVmZmVyXCIsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tQnVmZmVyKGJ1Zikge1xuICAgICAgICAgICAgYXNzZXJ0KEJ1ZmZlci5pc0J1ZmZlcihidWYpLCBcIkV4cGVjdGluZyBCdWZmZXJcIik7XG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwoYnVmLmxlbmd0aCwgNjQsIFwiQSBTaGE1MTIgQnVmZmVyIHNob3VsZCBiZSA2NCBjaGFyYWN0ZXJzIGxvbmcsIGluc3RlYWQgZ290IFwiICsgYnVmLmxlbmd0aCk7XG4gICAgICAgICAgICByZXR1cm4gQWVzLmZyb21TaGE1MTIoYnVmLnRvU3RyaW5nKFwiaGV4XCIpKTtcbiAgICAgICAgfVxuICAgICAgICAvKipcbiAgICAgICAgICAgIEB0aHJvd3Mge0Vycm9yfSAtIFwiSW52YWxpZCBLZXksIC4uLlwiXG4gICAgICAgICAgICBAYXJnIHtQcml2YXRlS2V5fSBwcml2YXRlX2tleSAtIHJlcXVpcmVkIGFuZCB1c2VkIGZvciBkZWNyeXB0aW9uXG4gICAgICAgICAgICBAYXJnIHtQdWJsaWNLZXl9IHB1YmxpY19rZXkgLSByZXF1aXJlZCBhbmQgdXNlZCB0byBjYWxjdWFsdGUgdGhlIHNoYXJlZCBzZWNyZXRcbiAgICAgICAgICAgIEBhcmcge3N0cmluZ30gW25vbmNlID0gXCJcIl0gb3B0aW9uYWwgYnV0IHNob3VsZCBhbHdheXMgYmUgcHJvdmlkZWQgYW5kIGJlIHVuaXF1ZSB3aGVuIHJlLXVzaW5nIHRoZSBzYW1lIHByaXZhdGUvcHVibGljIGtleXMgbW9yZSB0aGFuIG9uY2UuICBUaGlzIG5vbmNlIGlzIG5vdCBhIHNlY3JldC5cbiAgICAgICAgICAgIEBhcmcge3N0cmluZ3xCdWZmZXJ9IG1lc3NhZ2UgLSBFbmNyeXB0ZWQgbWVzc2FnZSBjb250YWluaW5nIGEgY2hlY2tzdW1cbiAgICAgICAgICAgIEByZXR1cm4ge0J1ZmZlcn1cbiAgICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiBcImRlY3J5cHRfd2l0aF9jaGVja3N1bVwiLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZGVjcnlwdF93aXRoX2NoZWNrc3VtKHByaXZhdGVfa2V5LCBwdWJsaWNfa2V5LCBub25jZSwgbWVzc2FnZSkge1xuICAgICAgICAgICAgdmFyIGxlZ2FjeSA9IGFyZ3VtZW50cy5sZW5ndGggPiA0ICYmIGFyZ3VtZW50c1s0XSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzRdIDogZmFsc2U7XG5cblxuICAgICAgICAgICAgLy8gV2FybmluZzogRG8gbm90IHB1dCBgbm9uY2UgPSBcIlwiYCBpbiB0aGUgYXJndW1lbnRzLCBpbiBlczYgdGhpcyB3aWxsIG5vdCBjb252ZXJ0IFwibnVsbFwiIGludG8gYW4gZW10cHkgc3RyaW5nXG4gICAgICAgICAgICBpZiAobm9uY2UgPT0gbnVsbCkgLy8gbnVsbCBvciB1bmRlZmluZWRcbiAgICAgICAgICAgICAgICBub25jZSA9IFwiXCI7XG5cbiAgICAgICAgICAgIGlmICghQnVmZmVyLmlzQnVmZmVyKG1lc3NhZ2UpKSB7XG4gICAgICAgICAgICAgICAgbWVzc2FnZSA9IG5ldyBCdWZmZXIobWVzc2FnZSwgJ2hleCcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgUyA9IHByaXZhdGVfa2V5LmdldF9zaGFyZWRfc2VjcmV0KHB1YmxpY19rZXksIGxlZ2FjeSk7XG4gICAgICAgICAgICAvLyBEIEUgQiBVIEdcbiAgICAgICAgICAgIC8vIGNvbnNvbGUubG9nKCdkZWNyeXB0X3dpdGhfY2hlY2tzdW0nLCB7XG4gICAgICAgICAgICAvLyAgICAgcHJpdl90b19wdWI6IHByaXZhdGVfa2V5LnRvUHVibGljS2V5KCkudG9TdHJpbmcoKSxcbiAgICAgICAgICAgIC8vICAgICBwdWI6IHB1YmxpY19rZXkudG9QdWJsaWNLZXlTdHJpbmcoKSxcbiAgICAgICAgICAgIC8vICAgICBub25jZTogbm9uY2UsXG4gICAgICAgICAgICAvLyAgICAgbWVzc2FnZTogbWVzc2FnZS5sZW5ndGgsXG4gICAgICAgICAgICAvLyAgICAgUzogUy50b1N0cmluZygnaGV4JylcbiAgICAgICAgICAgIC8vIH0pXG5cbiAgICAgICAgICAgIHZhciBhZXMgPSBBZXMuZnJvbVNlZWQoQnVmZmVyLmNvbmNhdChbXG4gICAgICAgICAgICAvLyBBIG51bGwgb3IgZW1wdHkgc3RyaW5nIG5vbmNlIHdpbGwgbm90IGVmZmVjdCB0aGUgaGFzaFxuICAgICAgICAgICAgbmV3IEJ1ZmZlcihcIlwiICsgbm9uY2UpLCBuZXcgQnVmZmVyKFMudG9TdHJpbmcoJ2hleCcpKV0pKTtcblxuICAgICAgICAgICAgdmFyIHBsYW5lYnVmZmVyID0gYWVzLmRlY3J5cHQobWVzc2FnZSk7XG4gICAgICAgICAgICBpZiAoIShwbGFuZWJ1ZmZlci5sZW5ndGggPj0gNCkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIGtleSwgY291bGQgbm90IGRlY3J5cHQgbWVzc2FnZSgxKVwiKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gREVCVUcgY29uc29sZS5sb2coJy4uLiBwbGFuZWJ1ZmZlcicscGxhbmVidWZmZXIpXG4gICAgICAgICAgICB2YXIgY2hlY2tzdW0gPSBwbGFuZWJ1ZmZlci5zbGljZSgwLCA0KTtcbiAgICAgICAgICAgIHZhciBwbGFpbnRleHQgPSBwbGFuZWJ1ZmZlci5zbGljZSg0KTtcblxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJy4uLiBjaGVja3N1bScsY2hlY2tzdW0udG9TdHJpbmcoJ2hleCcpKVxuICAgICAgICAgICAgLy8gY29uc29sZS5sb2coJy4uLiBwbGFpbnRleHQnLHBsYWludGV4dC50b1N0cmluZygpKVxuXG4gICAgICAgICAgICB2YXIgbmV3X2NoZWNrc3VtID0gaGFzaC5zaGEyNTYocGxhaW50ZXh0KTtcbiAgICAgICAgICAgIG5ld19jaGVja3N1bSA9IG5ld19jaGVja3N1bS5zbGljZSgwLCA0KTtcbiAgICAgICAgICAgIG5ld19jaGVja3N1bSA9IG5ld19jaGVja3N1bS50b1N0cmluZygnaGV4Jyk7XG5cbiAgICAgICAgICAgIGlmICghKGNoZWNrc3VtLnRvU3RyaW5nKCdoZXgnKSA9PT0gbmV3X2NoZWNrc3VtKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQga2V5LCBjb3VsZCBub3QgZGVjcnlwdCBtZXNzYWdlKDIpXCIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcGxhaW50ZXh0O1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6IFwiZW5jcnlwdF93aXRoX2NoZWNrc3VtXCIsXG5cblxuICAgICAgICAvKiogSWRlbnRpY2FsIHRvIHtAbGluayBkZWNyeXB0X3dpdGhfY2hlY2tzdW19IGJ1dCB1c2VkIHRvIGVuY3J5cHQuICBTaG91bGQgbm90IHRocm93IGFuIGVycm9yLlxuICAgICAgICAgICAgQHJldHVybiB7QnVmZmVyfSBtZXNzYWdlIC0gRW5jcnlwdGVkIG1lc3NhZ2Ugd2hpY2ggaW5jbHVkZXMgYSBjaGVja3N1bVxuICAgICAgICAqL1xuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZW5jcnlwdF93aXRoX2NoZWNrc3VtKHByaXZhdGVfa2V5LCBwdWJsaWNfa2V5LCBub25jZSwgbWVzc2FnZSkge1xuXG4gICAgICAgICAgICAvLyBXYXJuaW5nOiBEbyBub3QgcHV0IGBub25jZSA9IFwiXCJgIGluIHRoZSBhcmd1bWVudHMsIGluIGVzNiB0aGlzIHdpbGwgbm90IGNvbnZlcnQgXCJudWxsXCIgaW50byBhbiBlbXRweSBzdHJpbmdcblxuICAgICAgICAgICAgaWYgKG5vbmNlID09IG51bGwpIC8vIG51bGwgb3IgdW5kZWZpbmVkXG4gICAgICAgICAgICAgICAgbm9uY2UgPSBcIlwiO1xuXG4gICAgICAgICAgICBpZiAoIUJ1ZmZlci5pc0J1ZmZlcihtZXNzYWdlKSkge1xuICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBuZXcgQnVmZmVyKG1lc3NhZ2UsICdiaW5hcnknKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdmFyIFMgPSBwcml2YXRlX2tleS5nZXRfc2hhcmVkX3NlY3JldChwdWJsaWNfa2V5KTtcblxuICAgICAgICAgICAgLy8gRCBFIEIgVSBHXG4gICAgICAgICAgICAvLyBjb25zb2xlLmxvZygnZW5jcnlwdF93aXRoX2NoZWNrc3VtJywge1xuICAgICAgICAgICAgLy8gICAgIHByaXZfdG9fcHViOiBwcml2YXRlX2tleS50b1B1YmxpY0tleSgpLnRvU3RyaW5nKClcbiAgICAgICAgICAgIC8vICAgICBwdWI6IHB1YmxpY19rZXkudG9QdWJsaWNLZXlTdHJpbmcoKVxuICAgICAgICAgICAgLy8gICAgIG5vbmNlOiBub25jZVxuICAgICAgICAgICAgLy8gICAgIG1lc3NhZ2U6IG1lc3NhZ2UubGVuZ3RoXG4gICAgICAgICAgICAvLyAgICAgUzogUy50b1N0cmluZygnaGV4JylcbiAgICAgICAgICAgIC8vIH0pXG5cbiAgICAgICAgICAgIHZhciBhZXMgPSBBZXMuZnJvbVNlZWQoQnVmZmVyLmNvbmNhdChbXG4gICAgICAgICAgICAvLyBBIG51bGwgb3IgZW1wdHkgc3RyaW5nIG5vbmNlIHdpbGwgbm90IGVmZmVjdCB0aGUgaGFzaFxuICAgICAgICAgICAgbmV3IEJ1ZmZlcihcIlwiICsgbm9uY2UpLCBuZXcgQnVmZmVyKFMudG9TdHJpbmcoJ2hleCcpKV0pKTtcbiAgICAgICAgICAgIC8vIERFQlVHIGNvbnNvbGUubG9nKCcuLi4gUycsUy50b1N0cmluZygnaGV4JykpXG4gICAgICAgICAgICB2YXIgY2hlY2tzdW0gPSBoYXNoLnNoYTI1NihtZXNzYWdlKS5zbGljZSgwLCA0KTtcbiAgICAgICAgICAgIHZhciBwYXlsb2FkID0gQnVmZmVyLmNvbmNhdChbY2hlY2tzdW0sIG1lc3NhZ2VdKTtcbiAgICAgICAgICAgIC8vIERFQlVHIGNvbnNvbGUubG9nKCcuLi4gcGF5bG9hZCcscGF5bG9hZC50b1N0cmluZygpKVxuICAgICAgICAgICAgcmV0dXJuIGFlcy5lbmNyeXB0KHBheWxvYWQpO1xuICAgICAgICB9XG4gICAgfV0pO1xuXG4gICAgcmV0dXJuIEFlcztcbn0oKTtcblxubW9kdWxlLmV4cG9ydHMgPSBBZXM7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0Jyk7IC8vIGZyb20gZ2l0aHViLmNvbS9iaXRjb2luanMvYml0Y29pbmpzLWxpYiBmcm9tIGdpdGh1Yi5jb20vY3J5cHRvY29pbmpzL2VjZHNhXG52YXIgY3J5cHRvID0gcmVxdWlyZSgnLi9oYXNoJyk7XG52YXIgZW5mb3JjZVR5cGUgPSByZXF1aXJlKCcuL2VuZm9yY2VfdHlwZXMnKTtcblxudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCdiaWdpJyk7XG52YXIgRUNTaWduYXR1cmUgPSByZXF1aXJlKCcuL2Vjc2lnbmF0dXJlJyk7XG5cbi8vIGh0dHBzOi8vdG9vbHMuaWV0Zi5vcmcvaHRtbC9yZmM2OTc5I3NlY3Rpb24tMy4yXG5mdW5jdGlvbiBkZXRlcm1pbmlzdGljR2VuZXJhdGVLKGN1cnZlLCBoYXNoLCBkLCBjaGVja1NpZywgbm9uY2UpIHtcblxuICBlbmZvcmNlVHlwZSgnQnVmZmVyJywgaGFzaCk7XG4gIGVuZm9yY2VUeXBlKEJpZ0ludGVnZXIsIGQpO1xuXG4gIGlmIChub25jZSkge1xuICAgIGhhc2ggPSBjcnlwdG8uc2hhMjU2KEJ1ZmZlci5jb25jYXQoW2hhc2gsIG5ldyBCdWZmZXIobm9uY2UpXSkpO1xuICB9XG5cbiAgLy8gc2FuaXR5IGNoZWNrXG4gIGFzc2VydC5lcXVhbChoYXNoLmxlbmd0aCwgMzIsICdIYXNoIG11c3QgYmUgMjU2IGJpdCcpO1xuXG4gIHZhciB4ID0gZC50b0J1ZmZlcigzMik7XG4gIHZhciBrID0gbmV3IEJ1ZmZlcigzMik7XG4gIHZhciB2ID0gbmV3IEJ1ZmZlcigzMik7XG5cbiAgLy8gU3RlcCBCXG4gIHYuZmlsbCgxKTtcblxuICAvLyBTdGVwIENcbiAgay5maWxsKDApO1xuXG4gIC8vIFN0ZXAgRFxuICBrID0gY3J5cHRvLkhtYWNTSEEyNTYoQnVmZmVyLmNvbmNhdChbdiwgbmV3IEJ1ZmZlcihbMF0pLCB4LCBoYXNoXSksIGspO1xuXG4gIC8vIFN0ZXAgRVxuICB2ID0gY3J5cHRvLkhtYWNTSEEyNTYodiwgayk7XG5cbiAgLy8gU3RlcCBGXG4gIGsgPSBjcnlwdG8uSG1hY1NIQTI1NihCdWZmZXIuY29uY2F0KFt2LCBuZXcgQnVmZmVyKFsxXSksIHgsIGhhc2hdKSwgayk7XG5cbiAgLy8gU3RlcCBHXG4gIHYgPSBjcnlwdG8uSG1hY1NIQTI1Nih2LCBrKTtcblxuICAvLyBTdGVwIEgxL0gyYSwgaWdub3JlZCBhcyB0bGVuID09PSBxbGVuICgyNTYgYml0KVxuICAvLyBTdGVwIEgyYlxuICB2ID0gY3J5cHRvLkhtYWNTSEEyNTYodiwgayk7XG5cbiAgdmFyIFQgPSBCaWdJbnRlZ2VyLmZyb21CdWZmZXIodik7XG5cbiAgLy8gU3RlcCBIMywgcmVwZWF0IHVudGlsIFQgaXMgd2l0aGluIHRoZSBpbnRlcnZhbCBbMSwgbiAtIDFdXG4gIHdoaWxlIChULnNpZ251bSgpIDw9IDAgfHwgVC5jb21wYXJlVG8oY3VydmUubikgPj0gMCB8fCAhY2hlY2tTaWcoVCkpIHtcbiAgICBrID0gY3J5cHRvLkhtYWNTSEEyNTYoQnVmZmVyLmNvbmNhdChbdiwgbmV3IEJ1ZmZlcihbMF0pXSksIGspO1xuICAgIHYgPSBjcnlwdG8uSG1hY1NIQTI1Nih2LCBrKTtcblxuICAgIC8vIFN0ZXAgSDEvSDJhLCBhZ2FpbiwgaWdub3JlZCBhcyB0bGVuID09PSBxbGVuICgyNTYgYml0KVxuICAgIC8vIFN0ZXAgSDJiIGFnYWluXG4gICAgdiA9IGNyeXB0by5IbWFjU0hBMjU2KHYsIGspO1xuXG4gICAgVCA9IEJpZ0ludGVnZXIuZnJvbUJ1ZmZlcih2KTtcbiAgfVxuXG4gIHJldHVybiBUO1xufVxuXG5mdW5jdGlvbiBzaWduKGN1cnZlLCBoYXNoLCBkLCBub25jZSkge1xuXG4gIHZhciBlID0gQmlnSW50ZWdlci5mcm9tQnVmZmVyKGhhc2gpO1xuICB2YXIgbiA9IGN1cnZlLm47XG4gIHZhciBHID0gY3VydmUuRztcblxuICB2YXIgciwgcztcbiAgdmFyIGsgPSBkZXRlcm1pbmlzdGljR2VuZXJhdGVLKGN1cnZlLCBoYXNoLCBkLCBmdW5jdGlvbiAoaykge1xuICAgIC8vIGZpbmQgY2Fub25pY2FsbHkgdmFsaWQgc2lnbmF0dXJlXG4gICAgdmFyIFEgPSBHLm11bHRpcGx5KGspO1xuXG4gICAgaWYgKGN1cnZlLmlzSW5maW5pdHkoUSkpIHJldHVybiBmYWxzZTtcblxuICAgIHIgPSBRLmFmZmluZVgubW9kKG4pO1xuICAgIGlmIChyLnNpZ251bSgpID09PSAwKSByZXR1cm4gZmFsc2U7XG5cbiAgICBzID0gay5tb2RJbnZlcnNlKG4pLm11bHRpcGx5KGUuYWRkKGQubXVsdGlwbHkocikpKS5tb2Qobik7XG4gICAgaWYgKHMuc2lnbnVtKCkgPT09IDApIHJldHVybiBmYWxzZTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9LCBub25jZSk7XG5cbiAgdmFyIE5fT1ZFUl9UV08gPSBuLnNoaWZ0UmlnaHQoMSk7XG5cbiAgLy8gZW5mb3JjZSBsb3cgUyB2YWx1ZXMsIHNlZSBiaXA2MjogJ2xvdyBzIHZhbHVlcyBpbiBzaWduYXR1cmVzJ1xuICBpZiAocy5jb21wYXJlVG8oTl9PVkVSX1RXTykgPiAwKSB7XG4gICAgcyA9IG4uc3VidHJhY3Qocyk7XG4gIH1cblxuICByZXR1cm4gbmV3IEVDU2lnbmF0dXJlKHIsIHMpO1xufVxuXG5mdW5jdGlvbiB2ZXJpZnlSYXcoY3VydmUsIGUsIHNpZ25hdHVyZSwgUSkge1xuICB2YXIgbiA9IGN1cnZlLm47XG4gIHZhciBHID0gY3VydmUuRztcblxuICB2YXIgciA9IHNpZ25hdHVyZS5yO1xuICB2YXIgcyA9IHNpZ25hdHVyZS5zO1xuXG4gIC8vIDEuNC4xIEVuZm9yY2UgciBhbmQgcyBhcmUgYm90aCBpbnRlZ2VycyBpbiB0aGUgaW50ZXJ2YWwgWzEsIG4g4oiSIDFdXG4gIGlmIChyLnNpZ251bSgpIDw9IDAgfHwgci5jb21wYXJlVG8obikgPj0gMCkgcmV0dXJuIGZhbHNlO1xuICBpZiAocy5zaWdudW0oKSA8PSAwIHx8IHMuY29tcGFyZVRvKG4pID49IDApIHJldHVybiBmYWxzZTtcblxuICAvLyBjID0gc14tMSBtb2QgblxuICB2YXIgYyA9IHMubW9kSW52ZXJzZShuKTtcblxuICAvLyAxLjQuNCBDb21wdXRlIHUxID0gZXNe4oiSMSBtb2QgblxuICAvLyAgICAgICAgICAgICAgIHUyID0gcnNe4oiSMSBtb2QgblxuICB2YXIgdTEgPSBlLm11bHRpcGx5KGMpLm1vZChuKTtcbiAgdmFyIHUyID0gci5tdWx0aXBseShjKS5tb2Qobik7XG5cbiAgLy8gMS40LjUgQ29tcHV0ZSBSID0gKHhSLCB5UikgPSB1MUcgKyB1MlFcbiAgdmFyIFIgPSBHLm11bHRpcGx5VHdvKHUxLCBRLCB1Mik7XG5cbiAgLy8gMS40LjUgKGNvbnQuKSBFbmZvcmNlIFIgaXMgbm90IGF0IGluZmluaXR5XG4gIGlmIChjdXJ2ZS5pc0luZmluaXR5KFIpKSByZXR1cm4gZmFsc2U7XG5cbiAgLy8gMS40LjYgQ29udmVydCB0aGUgZmllbGQgZWxlbWVudCBSLnggdG8gYW4gaW50ZWdlclxuICB2YXIgeFIgPSBSLmFmZmluZVg7XG5cbiAgLy8gMS40LjcgU2V0IHYgPSB4UiBtb2QgblxuICB2YXIgdiA9IHhSLm1vZChuKTtcblxuICAvLyAxLjQuOCBJZiB2ID0gciwgb3V0cHV0IFwidmFsaWRcIiwgYW5kIGlmIHYgIT0gciwgb3V0cHV0IFwiaW52YWxpZFwiXG4gIHJldHVybiB2LmVxdWFscyhyKTtcbn1cblxuZnVuY3Rpb24gdmVyaWZ5KGN1cnZlLCBoYXNoLCBzaWduYXR1cmUsIFEpIHtcbiAgLy8gMS40LjIgSCA9IEhhc2goTSksIGFscmVhZHkgZG9uZSBieSB0aGUgdXNlclxuICAvLyAxLjQuMyBlID0gSFxuICB2YXIgZSA9IEJpZ0ludGVnZXIuZnJvbUJ1ZmZlcihoYXNoKTtcbiAgcmV0dXJuIHZlcmlmeVJhdyhjdXJ2ZSwgZSwgc2lnbmF0dXJlLCBRKTtcbn1cblxuLyoqXG4gICogUmVjb3ZlciBhIHB1YmxpYyBrZXkgZnJvbSBhIHNpZ25hdHVyZS5cbiAgKlxuICAqIFNlZSBTRUMgMTogRWxsaXB0aWMgQ3VydmUgQ3J5cHRvZ3JhcGh5LCBzZWN0aW9uIDQuMS42LCBcIlB1YmxpY1xuICAqIEtleSBSZWNvdmVyeSBPcGVyYXRpb25cIi5cbiAgKlxuICAqIGh0dHA6Ly93d3cuc2VjZy5vcmcvZG93bmxvYWQvYWlkLTc4MC9zZWMxLXYyLnBkZlxuICAqL1xuZnVuY3Rpb24gcmVjb3ZlclB1YktleShjdXJ2ZSwgZSwgc2lnbmF0dXJlLCBpKSB7XG4gIGFzc2VydC5zdHJpY3RFcXVhbChpICYgMywgaSwgJ1JlY292ZXJ5IHBhcmFtIGlzIG1vcmUgdGhhbiB0d28gYml0cycpO1xuXG4gIHZhciBuID0gY3VydmUubjtcbiAgdmFyIEcgPSBjdXJ2ZS5HO1xuXG4gIHZhciByID0gc2lnbmF0dXJlLnI7XG4gIHZhciBzID0gc2lnbmF0dXJlLnM7XG5cbiAgYXNzZXJ0KHIuc2lnbnVtKCkgPiAwICYmIHIuY29tcGFyZVRvKG4pIDwgMCwgJ0ludmFsaWQgciB2YWx1ZScpO1xuICBhc3NlcnQocy5zaWdudW0oKSA+IDAgJiYgcy5jb21wYXJlVG8obikgPCAwLCAnSW52YWxpZCBzIHZhbHVlJyk7XG5cbiAgLy8gQSBzZXQgTFNCIHNpZ25pZmllcyB0aGF0IHRoZSB5LWNvb3JkaW5hdGUgaXMgb2RkXG4gIHZhciBpc1lPZGQgPSBpICYgMTtcblxuICAvLyBUaGUgbW9yZSBzaWduaWZpY2FudCBiaXQgc3BlY2lmaWVzIHdoZXRoZXIgd2Ugc2hvdWxkIHVzZSB0aGVcbiAgLy8gZmlyc3Qgb3Igc2Vjb25kIGNhbmRpZGF0ZSBrZXkuXG4gIHZhciBpc1NlY29uZEtleSA9IGkgPj4gMTtcblxuICAvLyAxLjEgTGV0IHggPSByICsgam5cbiAgdmFyIHggPSBpc1NlY29uZEtleSA/IHIuYWRkKG4pIDogcjtcbiAgdmFyIFIgPSBjdXJ2ZS5wb2ludEZyb21YKGlzWU9kZCwgeCk7XG5cbiAgLy8gMS40IENoZWNrIHRoYXQgblIgaXMgYXQgaW5maW5pdHlcbiAgdmFyIG5SID0gUi5tdWx0aXBseShuKTtcbiAgYXNzZXJ0KGN1cnZlLmlzSW5maW5pdHkoblIpLCAnblIgaXMgbm90IGEgdmFsaWQgY3VydmUgcG9pbnQnKTtcblxuICAvLyBDb21wdXRlIC1lIGZyb20gZVxuICB2YXIgZU5lZyA9IGUubmVnYXRlKCkubW9kKG4pO1xuXG4gIC8vIDEuNi4xIENvbXB1dGUgUSA9IHJeLTEgKHNSIC0gIGVHKVxuICAvLyAgICAgICAgICAgICAgIFEgPSByXi0xIChzUiArIC1lRylcbiAgdmFyIHJJbnYgPSByLm1vZEludmVyc2Uobik7XG5cbiAgdmFyIFEgPSBSLm11bHRpcGx5VHdvKHMsIEcsIGVOZWcpLm11bHRpcGx5KHJJbnYpO1xuICBjdXJ2ZS52YWxpZGF0ZShRKTtcblxuICByZXR1cm4gUTtcbn1cblxuLyoqXG4gICogQ2FsY3VsYXRlIHB1YmtleSBleHRyYWN0aW9uIHBhcmFtZXRlci5cbiAgKlxuICAqIFdoZW4gZXh0cmFjdGluZyBhIHB1YmtleSBmcm9tIGEgc2lnbmF0dXJlLCB3ZSBoYXZlIHRvXG4gICogZGlzdGluZ3Vpc2ggZm91ciBkaWZmZXJlbnQgY2FzZXMuIFJhdGhlciB0aGFuIHB1dHRpbmcgdGhpc1xuICAqIGJ1cmRlbiBvbiB0aGUgdmVyaWZpZXIsIEJpdGNvaW4gaW5jbHVkZXMgYSAyLWJpdCB2YWx1ZSB3aXRoIHRoZVxuICAqIHNpZ25hdHVyZS5cbiAgKlxuICAqIFRoaXMgZnVuY3Rpb24gc2ltcGx5IHRyaWVzIGFsbCBmb3VyIGNhc2VzIGFuZCByZXR1cm5zIHRoZSB2YWx1ZVxuICAqIHRoYXQgcmVzdWx0ZWQgaW4gYSBzdWNjZXNzZnVsIHB1YmtleSByZWNvdmVyeS5cbiAgKi9cbmZ1bmN0aW9uIGNhbGNQdWJLZXlSZWNvdmVyeVBhcmFtKGN1cnZlLCBlLCBzaWduYXR1cmUsIFEpIHtcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCA0OyBpKyspIHtcbiAgICB2YXIgUXByaW1lID0gcmVjb3ZlclB1YktleShjdXJ2ZSwgZSwgc2lnbmF0dXJlLCBpKTtcblxuICAgIC8vIDEuNi4yIFZlcmlmeSBRXG4gICAgaWYgKFFwcmltZS5lcXVhbHMoUSkpIHtcbiAgICAgIHJldHVybiBpO1xuICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGZpbmQgdmFsaWQgcmVjb3ZlcnkgZmFjdG9yJyk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0ge1xuICBjYWxjUHViS2V5UmVjb3ZlcnlQYXJhbTogY2FsY1B1YktleVJlY292ZXJ5UGFyYW0sXG4gIGRldGVybWluaXN0aWNHZW5lcmF0ZUs6IGRldGVybWluaXN0aWNHZW5lcmF0ZUssXG4gIHJlY292ZXJQdWJLZXk6IHJlY292ZXJQdWJLZXksXG4gIHNpZ246IHNpZ24sXG4gIHZlcmlmeTogdmVyaWZ5LFxuICB2ZXJpZnlSYXc6IHZlcmlmeVJhd1xufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBhc3NlcnQgPSByZXF1aXJlKCdhc3NlcnQnKTsgLy8gZnJvbSBodHRwczovL2dpdGh1Yi5jb20vYml0Y29pbmpzL2JpdGNvaW5qcy1saWJcbnZhciBlbmZvcmNlVHlwZSA9IHJlcXVpcmUoJy4vZW5mb3JjZV90eXBlcycpO1xuXG52YXIgQmlnSW50ZWdlciA9IHJlcXVpcmUoJ2JpZ2knKTtcblxuZnVuY3Rpb24gRUNTaWduYXR1cmUociwgcykge1xuICBlbmZvcmNlVHlwZShCaWdJbnRlZ2VyLCByKTtcbiAgZW5mb3JjZVR5cGUoQmlnSW50ZWdlciwgcyk7XG5cbiAgdGhpcy5yID0gcjtcbiAgdGhpcy5zID0gcztcbn1cblxuLy8gSW1wb3J0IG9wZXJhdGlvbnNcbkVDU2lnbmF0dXJlLnBhcnNlQ29tcGFjdCA9IGZ1bmN0aW9uIChidWZmZXIpIHtcbiAgYXNzZXJ0LmVxdWFsKGJ1ZmZlci5sZW5ndGgsIDY1LCAnSW52YWxpZCBzaWduYXR1cmUgbGVuZ3RoJyk7XG4gIHZhciBpID0gYnVmZmVyLnJlYWRVSW50OCgwKSAtIDI3O1xuXG4gIC8vIEF0IG1vc3QgMyBiaXRzXG4gIGFzc2VydC5lcXVhbChpLCBpICYgNywgJ0ludmFsaWQgc2lnbmF0dXJlIHBhcmFtZXRlcicpO1xuICB2YXIgY29tcHJlc3NlZCA9ICEhKGkgJiA0KTtcblxuICAvLyBSZWNvdmVyeSBwYXJhbSBvbmx5XG4gIGkgPSBpICYgMztcblxuICB2YXIgciA9IEJpZ0ludGVnZXIuZnJvbUJ1ZmZlcihidWZmZXIuc2xpY2UoMSwgMzMpKTtcbiAgdmFyIHMgPSBCaWdJbnRlZ2VyLmZyb21CdWZmZXIoYnVmZmVyLnNsaWNlKDMzKSk7XG5cbiAgcmV0dXJuIHtcbiAgICBjb21wcmVzc2VkOiBjb21wcmVzc2VkLFxuICAgIGk6IGksXG4gICAgc2lnbmF0dXJlOiBuZXcgRUNTaWduYXR1cmUociwgcylcbiAgfTtcbn07XG5cbkVDU2lnbmF0dXJlLmZyb21ERVIgPSBmdW5jdGlvbiAoYnVmZmVyKSB7XG4gIGFzc2VydC5lcXVhbChidWZmZXIucmVhZFVJbnQ4KDApLCAweDMwLCAnTm90IGEgREVSIHNlcXVlbmNlJyk7XG4gIGFzc2VydC5lcXVhbChidWZmZXIucmVhZFVJbnQ4KDEpLCBidWZmZXIubGVuZ3RoIC0gMiwgJ0ludmFsaWQgc2VxdWVuY2UgbGVuZ3RoJyk7XG4gIGFzc2VydC5lcXVhbChidWZmZXIucmVhZFVJbnQ4KDIpLCAweDAyLCAnRXhwZWN0ZWQgYSBERVIgaW50ZWdlcicpO1xuXG4gIHZhciByTGVuID0gYnVmZmVyLnJlYWRVSW50OCgzKTtcbiAgYXNzZXJ0KHJMZW4gPiAwLCAnUiBsZW5ndGggaXMgemVybycpO1xuXG4gIHZhciBvZmZzZXQgPSA0ICsgckxlbjtcbiAgYXNzZXJ0LmVxdWFsKGJ1ZmZlci5yZWFkVUludDgob2Zmc2V0KSwgMHgwMiwgJ0V4cGVjdGVkIGEgREVSIGludGVnZXIgKDIpJyk7XG5cbiAgdmFyIHNMZW4gPSBidWZmZXIucmVhZFVJbnQ4KG9mZnNldCArIDEpO1xuICBhc3NlcnQoc0xlbiA+IDAsICdTIGxlbmd0aCBpcyB6ZXJvJyk7XG5cbiAgdmFyIHJCID0gYnVmZmVyLnNsaWNlKDQsIG9mZnNldCk7XG4gIHZhciBzQiA9IGJ1ZmZlci5zbGljZShvZmZzZXQgKyAyKTtcbiAgb2Zmc2V0ICs9IDIgKyBzTGVuO1xuXG4gIGlmIChyTGVuID4gMSAmJiByQi5yZWFkVUludDgoMCkgPT09IDB4MDApIHtcbiAgICBhc3NlcnQockIucmVhZFVJbnQ4KDEpICYgMHg4MCwgJ1IgdmFsdWUgZXhjZXNzaXZlbHkgcGFkZGVkJyk7XG4gIH1cblxuICBpZiAoc0xlbiA+IDEgJiYgc0IucmVhZFVJbnQ4KDApID09PSAweDAwKSB7XG4gICAgYXNzZXJ0KHNCLnJlYWRVSW50OCgxKSAmIDB4ODAsICdTIHZhbHVlIGV4Y2Vzc2l2ZWx5IHBhZGRlZCcpO1xuICB9XG5cbiAgYXNzZXJ0LmVxdWFsKG9mZnNldCwgYnVmZmVyLmxlbmd0aCwgJ0ludmFsaWQgREVSIGVuY29kaW5nJyk7XG4gIHZhciByID0gQmlnSW50ZWdlci5mcm9tREVSSW50ZWdlcihyQik7XG4gIHZhciBzID0gQmlnSW50ZWdlci5mcm9tREVSSW50ZWdlcihzQik7XG5cbiAgYXNzZXJ0KHIuc2lnbnVtKCkgPj0gMCwgJ1IgdmFsdWUgaXMgbmVnYXRpdmUnKTtcbiAgYXNzZXJ0KHMuc2lnbnVtKCkgPj0gMCwgJ1MgdmFsdWUgaXMgbmVnYXRpdmUnKTtcblxuICByZXR1cm4gbmV3IEVDU2lnbmF0dXJlKHIsIHMpO1xufTtcblxuLy8gRklYTUU6IDB4MDAsIDB4MDQsIDB4ODAgYXJlIFNJR0hBU0hfKiBib3VuZGFyeSBjb25zdGFudHMsIGltcG9ydGluZyBUcmFuc2FjdGlvbiBjYXVzZXMgYSBjaXJjdWxhciBkZXBlbmRlbmN5XG5FQ1NpZ25hdHVyZS5wYXJzZVNjcmlwdFNpZ25hdHVyZSA9IGZ1bmN0aW9uIChidWZmZXIpIHtcbiAgdmFyIGhhc2hUeXBlID0gYnVmZmVyLnJlYWRVSW50OChidWZmZXIubGVuZ3RoIC0gMSk7XG4gIHZhciBoYXNoVHlwZU1vZCA9IGhhc2hUeXBlICYgfjB4ODA7XG5cbiAgYXNzZXJ0KGhhc2hUeXBlTW9kID4gMHgwMCAmJiBoYXNoVHlwZU1vZCA8IDB4MDQsICdJbnZhbGlkIGhhc2hUeXBlJyk7XG5cbiAgcmV0dXJuIHtcbiAgICBzaWduYXR1cmU6IEVDU2lnbmF0dXJlLmZyb21ERVIoYnVmZmVyLnNsaWNlKDAsIC0xKSksXG4gICAgaGFzaFR5cGU6IGhhc2hUeXBlXG4gIH07XG59O1xuXG4vLyBFeHBvcnQgb3BlcmF0aW9uc1xuRUNTaWduYXR1cmUucHJvdG90eXBlLnRvQ29tcGFjdCA9IGZ1bmN0aW9uIChpLCBjb21wcmVzc2VkKSB7XG4gIGlmIChjb21wcmVzc2VkKSBpICs9IDQ7XG4gIGkgKz0gMjc7XG5cbiAgdmFyIGJ1ZmZlciA9IG5ldyBCdWZmZXIoNjUpO1xuICBidWZmZXIud3JpdGVVSW50OChpLCAwKTtcblxuICB0aGlzLnIudG9CdWZmZXIoMzIpLmNvcHkoYnVmZmVyLCAxKTtcbiAgdGhpcy5zLnRvQnVmZmVyKDMyKS5jb3B5KGJ1ZmZlciwgMzMpO1xuXG4gIHJldHVybiBidWZmZXI7XG59O1xuXG5FQ1NpZ25hdHVyZS5wcm90b3R5cGUudG9ERVIgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciByQmEgPSB0aGlzLnIudG9ERVJJbnRlZ2VyKCk7XG4gIHZhciBzQmEgPSB0aGlzLnMudG9ERVJJbnRlZ2VyKCk7XG5cbiAgdmFyIHNlcXVlbmNlID0gW107XG5cbiAgLy8gSU5URUdFUlxuICBzZXF1ZW5jZS5wdXNoKDB4MDIsIHJCYS5sZW5ndGgpO1xuICBzZXF1ZW5jZSA9IHNlcXVlbmNlLmNvbmNhdChyQmEpO1xuXG4gIC8vIElOVEVHRVJcbiAgc2VxdWVuY2UucHVzaCgweDAyLCBzQmEubGVuZ3RoKTtcbiAgc2VxdWVuY2UgPSBzZXF1ZW5jZS5jb25jYXQoc0JhKTtcblxuICAvLyBTRVFVRU5DRVxuICBzZXF1ZW5jZS51bnNoaWZ0KDB4MzAsIHNlcXVlbmNlLmxlbmd0aCk7XG5cbiAgcmV0dXJuIG5ldyBCdWZmZXIoc2VxdWVuY2UpO1xufTtcblxuRUNTaWduYXR1cmUucHJvdG90eXBlLnRvU2NyaXB0U2lnbmF0dXJlID0gZnVuY3Rpb24gKGhhc2hUeXBlKSB7XG4gIHZhciBoYXNoVHlwZUJ1ZmZlciA9IG5ldyBCdWZmZXIoMSk7XG4gIGhhc2hUeXBlQnVmZmVyLndyaXRlVUludDgoaGFzaFR5cGUsIDApO1xuXG4gIHJldHVybiBCdWZmZXIuY29uY2F0KFt0aGlzLnRvREVSKCksIGhhc2hUeXBlQnVmZmVyXSk7XG59O1xuXG5tb2R1bGUuZXhwb3J0cyA9IEVDU2lnbmF0dXJlOyIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBlbmZvcmNlKHR5cGUsIHZhbHVlKSB7XG4gIC8vIENvcGllZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9iaXRjb2luanMvYml0Y29pbmpzLWxpYlxuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdBcnJheSc6XG4gICAgICB7XG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbHVlKSkgcmV0dXJuO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgIGNhc2UgJ0Jvb2xlYW4nOlxuICAgICAge1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHJldHVybjtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBjYXNlICdCdWZmZXInOlxuICAgICAge1xuICAgICAgICBpZiAoQnVmZmVyLmlzQnVmZmVyKHZhbHVlKSkgcmV0dXJuO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cblxuICAgIGNhc2UgJ051bWJlcic6XG4gICAgICB7XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSByZXR1cm47XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgY2FzZSAnU3RyaW5nJzpcbiAgICAgIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHJldHVybjtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICBkZWZhdWx0OlxuICAgICAge1xuICAgICAgICBpZiAoZ2V0TmFtZSh2YWx1ZS5jb25zdHJ1Y3RvcikgPT09IGdldE5hbWUodHlwZSkpIHJldHVybjtcbiAgICAgIH1cbiAgfVxuXG4gIHRocm93IG5ldyBUeXBlRXJyb3IoJ0V4cGVjdGVkICcgKyAoZ2V0TmFtZSh0eXBlKSB8fCB0eXBlKSArICcsIGdvdCAnICsgdmFsdWUpO1xufTtcblxuZnVuY3Rpb24gZ2V0TmFtZShmbikge1xuICAvLyBXaHkgbm90IGZuLm5hbWU6IGh0dHBzOi8va2FuZ2F4LmdpdGh1Yi5pby9jb21wYXQtdGFibGUvZXM2LyNmdW5jdGlvbl9uYW1lX3Byb3BlcnR5XG4gIHZhciBtYXRjaCA9IGZuLnRvU3RyaW5nKCkubWF0Y2goL2Z1bmN0aW9uICguKj8pXFwoLyk7XG4gIHJldHVybiBtYXRjaCA/IG1hdGNoWzFdIDogbnVsbDtcbn0iLCJcInVzZSBzdHJpY3RcIjtcblxudmFyIGNyZWF0ZUhhc2ggPSByZXF1aXJlKFwiY3JlYXRlLWhhc2hcIik7XG52YXIgY3JlYXRlSG1hYyA9IHJlcXVpcmUoXCJjcmVhdGUtaG1hY1wiKTtcblxuLyoqIEBhcmcge3N0cmluZ3xCdWZmZXJ9IGRhdGFcbiAgICBAYXJnIHtzdHJpbmd9IFtkaWdlc3QgPSBudWxsXSAtICdoZXgnLCAnYmluYXJ5JyBvciAnYmFzZTY0J1xuICAgIEByZXR1cm4ge3N0cmluZ3xCdWZmZXJ9IC0gQnVmZmVyIHdoZW4gZGlnZXN0IGlzIG51bGwsIG9yIHN0cmluZ1xuKi9cbmZ1bmN0aW9uIHNoYTEoZGF0YSwgZW5jb2RpbmcpIHtcbiAgICByZXR1cm4gY3JlYXRlSGFzaCgnc2hhMScpLnVwZGF0ZShkYXRhKS5kaWdlc3QoZW5jb2RpbmcpO1xufVxuXG4vKiogQGFyZyB7c3RyaW5nfEJ1ZmZlcn0gZGF0YVxuICAgIEBhcmcge3N0cmluZ30gW2RpZ2VzdCA9IG51bGxdIC0gJ2hleCcsICdiaW5hcnknIG9yICdiYXNlNjQnXG4gICAgQHJldHVybiB7c3RyaW5nfEJ1ZmZlcn0gLSBCdWZmZXIgd2hlbiBkaWdlc3QgaXMgbnVsbCwgb3Igc3RyaW5nXG4qL1xuZnVuY3Rpb24gc2hhMjU2KGRhdGEsIGVuY29kaW5nKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTI1NicpLnVwZGF0ZShkYXRhKS5kaWdlc3QoZW5jb2RpbmcpO1xufVxuXG4vKiogQGFyZyB7c3RyaW5nfEJ1ZmZlcn0gZGF0YVxuICAgIEBhcmcge3N0cmluZ30gW2RpZ2VzdCA9IG51bGxdIC0gJ2hleCcsICdiaW5hcnknIG9yICdiYXNlNjQnXG4gICAgQHJldHVybiB7c3RyaW5nfEJ1ZmZlcn0gLSBCdWZmZXIgd2hlbiBkaWdlc3QgaXMgbnVsbCwgb3Igc3RyaW5nXG4qL1xuZnVuY3Rpb24gc2hhNTEyKGRhdGEsIGVuY29kaW5nKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUhhc2goJ3NoYTUxMicpLnVwZGF0ZShkYXRhKS5kaWdlc3QoZW5jb2RpbmcpO1xufVxuXG5mdW5jdGlvbiBIbWFjU0hBMjU2KGJ1ZmZlciwgc2VjcmV0KSB7XG4gICAgcmV0dXJuIGNyZWF0ZUhtYWMoJ3NoYTI1NicsIHNlY3JldCkudXBkYXRlKGJ1ZmZlcikuZGlnZXN0KCk7XG59XG5cbmZ1bmN0aW9uIHJpcGVtZDE2MChkYXRhKSB7XG4gICAgcmV0dXJuIGNyZWF0ZUhhc2goJ3JtZDE2MCcpLnVwZGF0ZShkYXRhKS5kaWdlc3QoKTtcbn1cblxuLy8gZnVuY3Rpb24gaGFzaDE2MChidWZmZXIpIHtcbi8vICAgcmV0dXJuIHJpcGVtZDE2MChzaGEyNTYoYnVmZmVyKSlcbi8vIH1cbi8vXG4vLyBmdW5jdGlvbiBoYXNoMjU2KGJ1ZmZlcikge1xuLy8gICByZXR1cm4gc2hhMjU2KHNoYTI1NihidWZmZXIpKVxuLy8gfVxuXG4vL1xuLy8gZnVuY3Rpb24gSG1hY1NIQTUxMihidWZmZXIsIHNlY3JldCkge1xuLy8gICByZXR1cm4gY3J5cHRvLmNyZWF0ZUhtYWMoJ3NoYTUxMicsIHNlY3JldCkudXBkYXRlKGJ1ZmZlcikuZGlnZXN0KClcbi8vIH1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gICAgc2hhMTogc2hhMSxcbiAgICBzaGEyNTY6IHNoYTI1NixcbiAgICBzaGE1MTI6IHNoYTUxMixcbiAgICBIbWFjU0hBMjU2OiBIbWFjU0hBMjU2LFxuICAgIHJpcGVtZDE2MDogcmlwZW1kMTYwXG4gICAgLy8gaGFzaDE2MDogaGFzaDE2MCxcbiAgICAvLyBoYXNoMjU2OiBoYXNoMjU2LFxuICAgIC8vIEhtYWNTSEE1MTI6IEhtYWNTSEE1MTJcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG52YXIgZWNkc2EgPSByZXF1aXJlKCcuL2VjZHNhJyk7XG52YXIgaGFzaCA9IHJlcXVpcmUoJy4vaGFzaCcpO1xuXG52YXIgX3JlcXVpcmUgPSByZXF1aXJlKCdlY3VydmUnKSxcbiAgICBnZXRDdXJ2ZUJ5TmFtZSA9IF9yZXF1aXJlLmdldEN1cnZlQnlOYW1lO1xuXG52YXIgc2VjcDI1NmsxID0gZ2V0Q3VydmVCeU5hbWUoJ3NlY3AyNTZrMScpO1xudmFyIGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpO1xudmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCdiaWdpJyk7XG52YXIgUHVibGljS2V5ID0gcmVxdWlyZSgnLi9QdWJsaWNLZXknKTtcblxudmFyIFNpZ25hdHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTaWduYXR1cmUocjEsIHMxLCBpMSkge1xuICAgICAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgU2lnbmF0dXJlKTtcblxuICAgICAgICB0aGlzLnIgPSByMTtcbiAgICAgICAgdGhpcy5zID0gczE7XG4gICAgICAgIHRoaXMuaSA9IGkxO1xuICAgICAgICBhc3NlcnQuZXF1YWwodGhpcy5yICE9IG51bGwsIHRydWUsICdNaXNzaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICBhc3NlcnQuZXF1YWwodGhpcy5zICE9IG51bGwsIHRydWUsICdNaXNzaW5nIHBhcmFtZXRlcicpO1xuICAgICAgICBhc3NlcnQuZXF1YWwodGhpcy5pICE9IG51bGwsIHRydWUsICdNaXNzaW5nIHBhcmFtZXRlcicpO1xuICAgIH1cblxuICAgIF9jcmVhdGVDbGFzcyhTaWduYXR1cmUsIFt7XG4gICAgICAgIGtleTogJ3RvQnVmZmVyJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvQnVmZmVyKCkge1xuICAgICAgICAgICAgdmFyIGJ1ZjtcbiAgICAgICAgICAgIGJ1ZiA9IG5ldyBCdWZmZXIoNjUpO1xuICAgICAgICAgICAgYnVmLndyaXRlVUludDgodGhpcy5pLCAwKTtcbiAgICAgICAgICAgIHRoaXMuci50b0J1ZmZlcigzMikuY29weShidWYsIDEpO1xuICAgICAgICAgICAgdGhpcy5zLnRvQnVmZmVyKDMyKS5jb3B5KGJ1ZiwgMzMpO1xuICAgICAgICAgICAgcmV0dXJuIGJ1ZjtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAncmVjb3ZlclB1YmxpY0tleUZyb21CdWZmZXInLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gcmVjb3ZlclB1YmxpY0tleUZyb21CdWZmZXIoYnVmZmVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yZWNvdmVyUHVibGljS2V5KGhhc2guc2hhMjU2KGJ1ZmZlcikpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdyZWNvdmVyUHVibGljS2V5JyxcblxuXG4gICAgICAgIC8qKlxuICAgICAgICAgICAgQHJldHVybiB7UHVibGljS2V5fVxuICAgICAgICAqL1xuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gcmVjb3ZlclB1YmxpY0tleShzaGEyNTZfYnVmZmVyKSB7XG4gICAgICAgICAgICB2YXIgUSA9IHZvaWQgMCxcbiAgICAgICAgICAgICAgICBlID0gdm9pZCAwLFxuICAgICAgICAgICAgICAgIGkgPSB2b2lkIDA7XG4gICAgICAgICAgICBlID0gQmlnSW50ZWdlci5mcm9tQnVmZmVyKHNoYTI1Nl9idWZmZXIpO1xuICAgICAgICAgICAgaSA9IHRoaXMuaTtcbiAgICAgICAgICAgIGkgLT0gMjc7XG4gICAgICAgICAgICBpID0gaSAmIDM7XG4gICAgICAgICAgICBRID0gZWNkc2EucmVjb3ZlclB1YktleShzZWNwMjU2azEsIGUsIHRoaXMsIGkpO1xuICAgICAgICAgICAgcmV0dXJuIFB1YmxpY0tleS5mcm9tUG9pbnQoUSk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3ZlcmlmeUJ1ZmZlcicsXG5cblxuICAgICAgICAvKipcbiAgICAgICAgICAgIEBwYXJhbSB7QnVmZmVyfSB1bi1oYXNoZWRcbiAgICAgICAgICAgIEBwYXJhbSB7Li9QdWJsaWNLZXl9XG4gICAgICAgICAgICBAcmV0dXJuIHtib29sZWFufVxuICAgICAgICAqL1xuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdmVyaWZ5QnVmZmVyKGJ1ZiwgcHVibGljX2tleSkge1xuICAgICAgICAgICAgdmFyIF9oYXNoID0gaGFzaC5zaGEyNTYoYnVmKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZlcmlmeUhhc2goX2hhc2gsIHB1YmxpY19rZXkpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICd2ZXJpZnlIYXNoJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZlcmlmeUhhc2goaGFzaCwgcHVibGljX2tleSkge1xuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGhhc2gubGVuZ3RoLCAzMiwgXCJBIFNIQSAyNTYgc2hvdWxkIGJlIDMyIGJ5dGVzIGxvbmcsIGluc3RlYWQgZ290IFwiICsgaGFzaC5sZW5ndGgpO1xuICAgICAgICAgICAgcmV0dXJuIGVjZHNhLnZlcmlmeShzZWNwMjU2azEsIGhhc2gsIHtcbiAgICAgICAgICAgICAgICByOiB0aGlzLnIsXG4gICAgICAgICAgICAgICAgczogdGhpcy5zXG4gICAgICAgICAgICB9LCBwdWJsaWNfa2V5LlEpO1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICd0b0J5dGVCdWZmZXInLFxuXG5cbiAgICAgICAgLyogPEhFWD4gKi9cblxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdG9CeXRlQnVmZmVyKCkge1xuICAgICAgICAgICAgdmFyIGI7XG4gICAgICAgICAgICBiID0gbmV3IEJ5dGVCdWZmZXIoQnl0ZUJ1ZmZlci5ERUZBVUxUX0NBUEFDSVRZLCBCeXRlQnVmZmVyLkxJVFRMRV9FTkRJQU4pO1xuICAgICAgICAgICAgdGhpcy5hcHBlbmRCeXRlQnVmZmVyKGIpO1xuICAgICAgICAgICAgcmV0dXJuIGIuY29weSgwLCBiLm9mZnNldCk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3RvSGV4JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvSGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9CdWZmZXIoKS50b1N0cmluZyhcImhleFwiKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndmVyaWZ5SGV4JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHZlcmlmeUhleChoZXgsIHB1YmxpY19rZXkpIHtcbiAgICAgICAgICAgIHZhciBidWY7XG4gICAgICAgICAgICBidWYgPSBuZXcgQnVmZmVyKGhleCwgJ2hleCcpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmVyaWZ5QnVmZmVyKGJ1ZiwgcHVibGljX2tleSk7XG4gICAgICAgIH1cbiAgICB9XSwgW3tcbiAgICAgICAga2V5OiAnZnJvbUJ1ZmZlcicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tQnVmZmVyKGJ1Zikge1xuICAgICAgICAgICAgdmFyIGksIHIsIHM7XG4gICAgICAgICAgICBhc3NlcnQuZXF1YWwoYnVmLmxlbmd0aCwgNjUsICdJbnZhbGlkIHNpZ25hdHVyZSBsZW5ndGgnKTtcbiAgICAgICAgICAgIGkgPSBidWYucmVhZFVJbnQ4KDApO1xuICAgICAgICAgICAgYXNzZXJ0LmVxdWFsKGkgLSAyNywgaSAtIDI3ICYgNywgJ0ludmFsaWQgc2lnbmF0dXJlIHBhcmFtZXRlcicpO1xuICAgICAgICAgICAgciA9IEJpZ0ludGVnZXIuZnJvbUJ1ZmZlcihidWYuc2xpY2UoMSwgMzMpKTtcbiAgICAgICAgICAgIHMgPSBCaWdJbnRlZ2VyLmZyb21CdWZmZXIoYnVmLnNsaWNlKDMzKSk7XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNpZ25hdHVyZShyLCBzLCBpKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnc2lnbkJ1ZmZlcicsXG5cblxuICAgICAgICAvKipcbiAgICAgICAgICAgIEBwYXJhbSB7QnVmZmVyfSBidWZcbiAgICAgICAgICAgIEBwYXJhbSB7UHJpdmF0ZUtleX0gcHJpdmF0ZV9rZXlcbiAgICAgICAgICAgIEByZXR1cm4ge1NpZ25hdHVyZX1cbiAgICAgICAgKi9cbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHNpZ25CdWZmZXIoYnVmLCBwcml2YXRlX2tleSkge1xuICAgICAgICAgICAgdmFyIF9oYXNoID0gaGFzaC5zaGEyNTYoYnVmKTtcbiAgICAgICAgICAgIHJldHVybiBTaWduYXR1cmUuc2lnbkJ1ZmZlclNoYTI1NihfaGFzaCwgcHJpdmF0ZV9rZXkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqIFNpZ24gYSBidWZmZXIgb2YgZXhhY3RhbGx5IDMyIGJ5dGVzIGluIHNpemUgKHNoYTI1Nih0ZXh0KSlcbiAgICAgICAgICAgIEBwYXJhbSB7QnVmZmVyfSBidWYgLSAzMiBieXRlcyBiaW5hcnlcbiAgICAgICAgICAgIEBwYXJhbSB7UHJpdmF0ZUtleX0gcHJpdmF0ZV9rZXlcbiAgICAgICAgICAgIEByZXR1cm4ge1NpZ25hdHVyZX1cbiAgICAgICAgKi9cblxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnc2lnbkJ1ZmZlclNoYTI1NicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzaWduQnVmZmVyU2hhMjU2KGJ1Zl9zaGEyNTYsIHByaXZhdGVfa2V5KSB7XG4gICAgICAgICAgICBpZiAoYnVmX3NoYTI1Ni5sZW5ndGggIT09IDMyIHx8ICFCdWZmZXIuaXNCdWZmZXIoYnVmX3NoYTI1NikpIHRocm93IG5ldyBFcnJvcihcImJ1Zl9zaGEyNTY6IDMyIGJ5dGUgYnVmZmVyIHJlcXVyZWRcIik7XG4gICAgICAgICAgICB2YXIgZGVyLCBlLCBlY3NpZ25hdHVyZSwgaSwgbGVuUiwgbGVuUywgbm9uY2U7XG4gICAgICAgICAgICBpID0gbnVsbDtcbiAgICAgICAgICAgIG5vbmNlID0gMDtcbiAgICAgICAgICAgIGUgPSBCaWdJbnRlZ2VyLmZyb21CdWZmZXIoYnVmX3NoYTI1Nik7XG4gICAgICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgICAgICAgIGVjc2lnbmF0dXJlID0gZWNkc2Euc2lnbihzZWNwMjU2azEsIGJ1Zl9zaGEyNTYsIHByaXZhdGVfa2V5LmQsIG5vbmNlKyspO1xuICAgICAgICAgICAgICAgIGRlciA9IGVjc2lnbmF0dXJlLnRvREVSKCk7XG4gICAgICAgICAgICAgICAgbGVuUiA9IGRlclszXTtcbiAgICAgICAgICAgICAgICBsZW5TID0gZGVyWzUgKyBsZW5SXTtcbiAgICAgICAgICAgICAgICBpZiAobGVuUiA9PT0gMzIgJiYgbGVuUyA9PT0gMzIpIHtcbiAgICAgICAgICAgICAgICAgICAgaSA9IGVjZHNhLmNhbGNQdWJLZXlSZWNvdmVyeVBhcmFtKHNlY3AyNTZrMSwgZSwgZWNzaWduYXR1cmUsIHByaXZhdGVfa2V5LnRvUHVibGljS2V5KCkuUSk7XG4gICAgICAgICAgICAgICAgICAgIGkgKz0gNDsgLy8gY29tcHJlc3NlZFxuICAgICAgICAgICAgICAgICAgICBpICs9IDI3OyAvLyBjb21wYWN0ICAvLyAgMjQgb3IgMjcgOiggZm9yY2luZyBvZGQteSAybmQga2V5IGNhbmRpZGF0ZSlcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChub25jZSAlIDEwID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiV0FSTjogXCIgKyBub25jZSArIFwiIGF0dGVtcHRzIHRvIGZpbmQgY2Fub25pY2FsIHNpZ25hdHVyZVwiKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gbmV3IFNpZ25hdHVyZShlY3NpZ25hdHVyZS5yLCBlY3NpZ25hdHVyZS5zLCBpKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnc2lnbicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzaWduKHN0cmluZywgcHJpdmF0ZV9rZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBTaWduYXR1cmUuc2lnbkJ1ZmZlcihuZXcgQnVmZmVyKHN0cmluZyksIHByaXZhdGVfa2V5KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnZnJvbUhleCcsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tSGV4KGhleCkge1xuICAgICAgICAgICAgcmV0dXJuIFNpZ25hdHVyZS5mcm9tQnVmZmVyKG5ldyBCdWZmZXIoaGV4LCBcImhleFwiKSk7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3NpZ25IZXgnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gc2lnbkhleChoZXgsIHByaXZhdGVfa2V5KSB7XG4gICAgICAgICAgICB2YXIgYnVmO1xuICAgICAgICAgICAgYnVmID0gbmV3IEJ1ZmZlcihoZXgsICdoZXgnKTtcbiAgICAgICAgICAgIHJldHVybiBTaWduYXR1cmUuc2lnbkJ1ZmZlcihidWYsIHByaXZhdGVfa2V5KTtcbiAgICAgICAgfVxuICAgIH1dKTtcblxuICAgIHJldHVybiBTaWduYXR1cmU7XG59KCk7XG5cbm1vZHVsZS5leHBvcnRzID0gU2lnbmF0dXJlOyIsIid1c2Ugc3RyaWN0JztcblxubW9kdWxlLmV4cG9ydHMgPSB7XG5cbiAgICAvLyBQcmltYXJ5IGNsYXNzIGZvciBjcmVhdGluZyBvcGVyYXRpb25zXG4gICAgU2VyaWFsaXplcjogcmVxdWlyZSgnLi9zcmMvc2VyaWFsaXplcicpLFxuXG4gICAgLy8gaGVscGVyIGZ1bmN0aW9ucyBmb3IgY3JlYXRpbmcgb3BlcmF0aW9uc1xuICAgIGZwOiByZXF1aXJlKCcuL3NyYy9GYXN0UGFyc2VyJyksXG5cbiAgICAvLyBMb3cgbGV2ZWwgdHlwZXNcbiAgICB0eXBlczogcmVxdWlyZSgnLi9zcmMvdHlwZXMnKSxcblxuICAgIC8vIEhpZ2hlciBsZXZlbCBvcGVyYXRpb25zIChtYWRlIG91dCBvZiBnZW5lcmljIHR5cGVzKVxuICAgIG9wczogcmVxdWlyZSgnLi9zcmMvb3BlcmF0aW9ucycpLFxuXG4gICAgLy8gVXRpbGl0eSB0aGF0IGdlbmVyYXRlcyBKU09OIGV4YW1wbGVzXG4gICAgdGVtcGxhdGU6IHJlcXVpcmUoJy4vc3JjL3RlbXBsYXRlJyksXG5cbiAgICAvLyBTZXJpYWxpemVyIHZhbGlkYXRpb25cbiAgICBTZXJpYWxpemVyVmFsaWRhdGlvbjogcmVxdWlyZSgnLi9zcmMvU2VyaWFsaXplclZhbGlkYXRpb24nKVxufTsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBQdWJsaWNLZXkgPSByZXF1aXJlKFwiLi4vLi4vZWNjL3NyYy9QdWJsaWNLZXlcIik7XG5cbnZhciBGYXN0UGFyc2VyID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEZhc3RQYXJzZXIoKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBGYXN0UGFyc2VyKTtcbiAgICB9XG5cbiAgICBfY3JlYXRlQ2xhc3MoRmFzdFBhcnNlciwgbnVsbCwgW3tcbiAgICAgICAga2V5OiAnZml4ZWRfZGF0YScsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmaXhlZF9kYXRhKGIsIGxlbiwgYnVmZmVyKSB7XG4gICAgICAgICAgICBpZiAoIWIpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYnVmZmVyKSB7XG4gICAgICAgICAgICAgICAgdmFyIGRhdGEgPSBidWZmZXIuc2xpY2UoMCwgbGVuKS50b1N0cmluZygnYmluYXJ5Jyk7XG4gICAgICAgICAgICAgICAgYi5hcHBlbmQoZGF0YSwgJ2JpbmFyeScpO1xuICAgICAgICAgICAgICAgIHdoaWxlIChsZW4tLSA+IGRhdGEubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGIud3JpdGVVaW50OCgwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhciBiX2NvcHkgPSBiLmNvcHkoYi5vZmZzZXQsIGIub2Zmc2V0ICsgbGVuKTtcbiAgICAgICAgICAgICAgICBiLnNraXAobGVuKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEJ1ZmZlcihiX2NvcHkudG9CaW5hcnkoKSwgJ2JpbmFyeScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdwdWJsaWNfa2V5JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHB1YmxpY19rZXkoYiwgX3B1YmxpY19rZXkpIHtcbiAgICAgICAgICAgIGlmICghYikge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChfcHVibGljX2tleSkge1xuICAgICAgICAgICAgICAgIHZhciBidWZmZXIgPSBfcHVibGljX2tleS50b0J1ZmZlcigpO1xuICAgICAgICAgICAgICAgIGIuYXBwZW5kKGJ1ZmZlci50b1N0cmluZygnYmluYXJ5JyksICdiaW5hcnknKTtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGJ1ZmZlciA9IEZhc3RQYXJzZXIuZml4ZWRfZGF0YShiLCAzMyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFB1YmxpY0tleS5mcm9tQnVmZmVyKGJ1ZmZlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3JpcGVtZDE2MCcsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiByaXBlbWQxNjAoYiwgX3JpcGVtZCkge1xuICAgICAgICAgICAgaWYgKCFiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF9yaXBlbWQpIHtcbiAgICAgICAgICAgICAgICBGYXN0UGFyc2VyLmZpeGVkX2RhdGEoYiwgMjAsIF9yaXBlbWQpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZhc3RQYXJzZXIuZml4ZWRfZGF0YShiLCAyMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3NoYTI1NicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBzaGEyNTYoYiwgX3NoYSkge1xuICAgICAgICAgICAgaWYgKCFiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKF9zaGEpIHtcbiAgICAgICAgICAgICAgICBGYXN0UGFyc2VyLmZpeGVkX2RhdGEoYiwgMzIsIF9zaGEpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEZhc3RQYXJzZXIuZml4ZWRfZGF0YShiLCAzMik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3RpbWVfcG9pbnRfc2VjJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRpbWVfcG9pbnRfc2VjKGIsIGVwb2NoKSB7XG4gICAgICAgICAgICBpZiAoZXBvY2gpIHtcbiAgICAgICAgICAgICAgICBlcG9jaCA9IE1hdGguY2VpbChlcG9jaCAvIDEwMDApO1xuICAgICAgICAgICAgICAgIGIud3JpdGVJbnQzMihlcG9jaCk7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlcG9jaCA9IGIucmVhZEludDMyKCk7IC8vIGZjOjp0aW1lX3BvaW50X3NlY1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgRGF0ZShlcG9jaCAqIDEwMDApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfV0pO1xuXG4gICAgcmV0dXJuIEZhc3RQYXJzZXI7XG59KCk7XG5cbm1vZHVsZS5leHBvcnRzID0gRmFzdFBhcnNlcjsiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfdHlwZW9mID0gdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIHR5cGVvZiBTeW1ib2wuaXRlcmF0b3IgPT09IFwic3ltYm9sXCIgPyBmdW5jdGlvbiAob2JqKSB7IHJldHVybiB0eXBlb2Ygb2JqOyB9IDogZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajsgfTtcblxudmFyIF9yZXF1aXJlID0gcmVxdWlyZSgnYnl0ZWJ1ZmZlcicpLFxuICAgIExvbmcgPSBfcmVxdWlyZS5Mb25nO1xuXG52YXIgQ2hhaW5UeXBlcyA9IHJlcXVpcmUoJy4uLy4uL2NoYWluL3NyYy9DaGFpblR5cGVzJyk7XG5cbnZhciBNQVhfU0FGRV9JTlQgPSA5MDA3MTk5MjU0NzQwOTkxO1xudmFyIE1JTl9TQUZFX0lOVCA9IC05MDA3MTk5MjU0NzQwOTkxO1xuXG4vKipcbiAgICBNb3N0IHZhbGlkYXRpb25zIGFyZSBza2lwcGVkIGFuZCB0aGUgdmFsdWUgcmV0dXJuZWQgdW5jaGFuZ2VkIHdoZW4gYW4gZW1wdHkgc3RyaW5nLCBudWxsLCBvciB1bmRlZmluZWQgaXMgZW5jb3VudGVyZWQgKGV4Y2VwdCBcInJlcXVpcmVkXCIpLlxuXG4gICAgVmFsaWRhdGlvbnMgc3VwcG9ydCBhIHN0cmluZyBmb3JtYXQgZm9yIGRlYWxpbmcgd2l0aCBsYXJnZSBudW1iZXJzLlxuKi9cbnZhciBfbXkgPSB7XG5cbiAgICBpc19lbXB0eTogZnVuY3Rpb24gaXNfZW1wdHkodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQ7XG4gICAgfSxcblxuICAgIHJlcXVpcmVkOiBmdW5jdGlvbiByZXF1aXJlZCh2YWx1ZSkge1xuICAgICAgICB2YXIgZmllbGRfbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogXCJcIjtcblxuICAgICAgICBpZiAodGhpcy5pc19lbXB0eSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndmFsdWUgcmVxdWlyZWQgJyArIGZpZWxkX25hbWUgKyAnICcgKyB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH0sXG4gICAgcmVxdWlyZV9sb25nOiBmdW5jdGlvbiByZXF1aXJlX2xvbmcodmFsdWUpIHtcbiAgICAgICAgdmFyIGZpZWxkX25hbWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IFwiXCI7XG5cbiAgICAgICAgaWYgKCFMb25nLmlzTG9uZyh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTG9uZyB2YWx1ZSByZXF1aXJlZCAnICsgZmllbGRfbmFtZSArICcgJyArIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSxcbiAgICBzdHJpbmc6IGZ1bmN0aW9uIHN0cmluZyh2YWx1ZSkge1xuICAgICAgICBpZiAodGhpcy5pc19lbXB0eSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3N0cmluZyByZXF1aXJlZDogJyArIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSxcbiAgICBudW1iZXI6IGZ1bmN0aW9uIG51bWJlcih2YWx1ZSkge1xuICAgICAgICBpZiAodGhpcy5pc19lbXB0eSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ251bWJlciByZXF1aXJlZDogJyArIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSxcbiAgICB3aG9sZV9udW1iZXI6IGZ1bmN0aW9uIHdob2xlX251bWJlcih2YWx1ZSkge1xuICAgICAgICB2YXIgZmllbGRfbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogXCJcIjtcblxuICAgICAgICBpZiAodGhpcy5pc19lbXB0eSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoL1xcLi8udGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignd2hvbGUgbnVtYmVyIHJlcXVpcmVkICcgKyBmaWVsZF9uYW1lICsgJyAnICsgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuICAgIHVuc2lnbmVkOiBmdW5jdGlvbiB1bnNpZ25lZCh2YWx1ZSkge1xuICAgICAgICB2YXIgZmllbGRfbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogXCJcIjtcblxuICAgICAgICBpZiAodGhpcy5pc19lbXB0eSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoLy0vLnRlc3QodmFsdWUpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Vuc2lnbmVkIHJlcXVpcmVkICcgKyBmaWVsZF9uYW1lICsgJyAnICsgdmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuXG5cbiAgICBpc19kaWdpdHM6IGZ1bmN0aW9uIGlzX2RpZ2l0cyh2YWx1ZSkge1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm51bWVyaWNcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuICgvXlswLTldKyQvLnRlc3QodmFsdWUpXG4gICAgICAgICk7XG4gICAgfSxcblxuICAgIHRvX251bWJlcjogZnVuY3Rpb24gdG9fbnVtYmVyKHZhbHVlKSB7XG4gICAgICAgIHZhciBmaWVsZF9uYW1lID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiBcIlwiO1xuXG4gICAgICAgIGlmICh0aGlzLmlzX2VtcHR5KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMubm9fb3ZlcmZsb3c1Myh2YWx1ZSwgZmllbGRfbmFtZSk7XG4gICAgICAgIHZhciBpbnRfdmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcGFyc2VJbnQodmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KCk7XG4gICAgICAgIHJldHVybiBpbnRfdmFsdWU7XG4gICAgfSxcblxuICAgIHRvX2xvbmc6IGZ1bmN0aW9uIHRvX2xvbmcodmFsdWUpIHtcbiAgICAgICAgdmFyIGZpZWxkX25hbWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IFwiXCI7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNfZW1wdHkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKExvbmcuaXNMb25nKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ub19vdmVyZmxvdzY0KHZhbHVlLCBmaWVsZF9uYW1lKTtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdmFsdWUgPSBcIlwiICsgdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIExvbmcuZnJvbVN0cmluZyh2YWx1ZSk7XG4gICAgfSxcbiAgICB0b191bG9uZzogZnVuY3Rpb24gdG9fdWxvbmcodmFsdWUpIHtcbiAgICAgICAgdmFyIGZpZWxkX25hbWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IFwiXCI7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNfZW1wdHkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKExvbmcuaXNMb25nKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5ub19vdmVyZmxvdzY0KHZhbHVlLCBmaWVsZF9uYW1lLCB0cnVlKTtcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdmFsdWUgPSBcIlwiICsgdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIExvbmcuZnJvbVN0cmluZyh2YWx1ZSwgdHJ1ZSk7XG4gICAgfSxcbiAgICB0b19zdHJpbmc6IGZ1bmN0aW9uIHRvX3N0cmluZyh2YWx1ZSkge1xuICAgICAgICB2YXIgZmllbGRfbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogXCJcIjtcblxuICAgICAgICBpZiAodGhpcy5pc19lbXB0eSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgdGhpcy5ub19vdmVyZmxvdzUzKHZhbHVlLCBmaWVsZF9uYW1lKTtcbiAgICAgICAgICAgIHJldHVybiBcIlwiICsgdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKExvbmcuaXNMb25nKHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgJ3Vuc3VwcG9ydGVkIHR5cGUgJyArIGZpZWxkX25hbWUgKyAnOiAoJyArICh0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKHZhbHVlKSkgKyAnKSAnICsgdmFsdWU7XG4gICAgfSxcbiAgICByZXF1aXJlX3Rlc3Q6IGZ1bmN0aW9uIHJlcXVpcmVfdGVzdChyZWdleCwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGZpZWxkX25hbWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IFwiXCI7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNfZW1wdHkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFyZWdleC50ZXN0KHZhbHVlKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd1bm1hdGNoZWQgJyArIHJlZ2V4ICsgJyAnICsgZmllbGRfbmFtZSArICcgJyArIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSxcblxuXG4gICAgcmVxdWlyZV9tYXRjaDogZnVuY3Rpb24gcmVxdWlyZV9tYXRjaChyZWdleCwgdmFsdWUpIHtcbiAgICAgICAgdmFyIGZpZWxkX25hbWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IFwiXCI7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNfZW1wdHkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1hdGNoID0gdmFsdWUubWF0Y2gocmVnZXgpO1xuICAgICAgICBpZiAobWF0Y2ggPT09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndW5tYXRjaGVkICcgKyByZWdleCArICcgJyArIGZpZWxkX25hbWUgKyAnICcgKyB2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG1hdGNoO1xuICAgIH0sXG5cbiAgICByZXF1aXJlX29iamVjdF9pZDogZnVuY3Rpb24gcmVxdWlyZV9vYmplY3RfaWQodmFsdWUsIGZpZWxkX25hbWUpIHtcbiAgICAgICAgcmV0dXJuIHJlcXVpcmVfbWF0Y2goL14oWzAtOV0rKVxcLihbMC05XSspXFwuKFswLTldKykkLywgdmFsdWUsIGZpZWxkX25hbWUpO1xuICAgIH0sXG5cbiAgICAvLyBEb2VzIG5vdCBzdXBwb3J0IG92ZXIgNTMgYml0c1xuICAgIHJlcXVpcmVfcmFuZ2U6IGZ1bmN0aW9uIHJlcXVpcmVfcmFuZ2UobWluLCBtYXgsIHZhbHVlKSB7XG4gICAgICAgIHZhciBmaWVsZF9uYW1lID0gYXJndW1lbnRzLmxlbmd0aCA+IDMgJiYgYXJndW1lbnRzWzNdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbM10gOiBcIlwiO1xuXG4gICAgICAgIGlmICh0aGlzLmlzX2VtcHR5KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHZhciBudW1iZXIgPSB0aGlzLnRvX251bWJlcih2YWx1ZSk7XG4gICAgICAgIGlmICh2YWx1ZSA8IG1pbiB8fCB2YWx1ZSA+IG1heCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdvdXQgb2YgcmFuZ2UgJyArIHZhbHVlICsgJyAnICsgZmllbGRfbmFtZSArICcgJyArIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSxcblxuXG4gICAgcmVxdWlyZV9vYmplY3RfdHlwZTogZnVuY3Rpb24gcmVxdWlyZV9vYmplY3RfdHlwZSgpIHtcbiAgICAgICAgdmFyIHJlc2VydmVkX3NwYWNlcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogMTtcbiAgICAgICAgdmFyIHR5cGUgPSBhcmd1bWVudHNbMV07XG4gICAgICAgIHZhciB2YWx1ZSA9IGFyZ3VtZW50c1syXTtcbiAgICAgICAgdmFyIGZpZWxkX25hbWUgPSBhcmd1bWVudHMubGVuZ3RoID4gMyAmJiBhcmd1bWVudHNbM10gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1szXSA6IFwiXCI7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNfZW1wdHkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG9iamVjdF90eXBlID0gQ2hhaW5UeXBlcy5vYmplY3RfdHlwZVt0eXBlXTtcbiAgICAgICAgaWYgKCFvYmplY3RfdHlwZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIG9iamVjdCB0eXBlICcgKyB0eXBlICsgJyAnICsgZmllbGRfbmFtZSArICcgJyArIHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmUgPSBuZXcgUmVnRXhwKHJlc2VydmVkX3NwYWNlcyArICcuJyArIG9iamVjdF90eXBlICsgJy5bMC05XSskJyk7XG4gICAgICAgIGlmICghcmUudGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0aW5nICcgKyB0eXBlICsgJyBpbiBmb3JtYXQgJyArIChyZXNlcnZlZF9zcGFjZXMgKyAnLicgKyBvYmplY3RfdHlwZSArICcuWzAtOV0rICcpICsgKCdpbnN0ZWFkIG9mICcgKyB2YWx1ZSArICcgJyArIGZpZWxkX25hbWUgKyAnICcgKyB2YWx1ZSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuXG4gICAgZ2V0X2luc3RhbmNlOiBmdW5jdGlvbiBnZXRfaW5zdGFuY2UocmVzZXJ2ZV9zcGFjZXMsIHR5cGUsIHZhbHVlLCBmaWVsZF9uYW1lKSB7XG4gICAgICAgIGlmICh0aGlzLmlzX2VtcHR5KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVxdWlyZV9vYmplY3RfdHlwZShyZXNlcnZlX3NwYWNlcywgdHlwZSwgdmFsdWUsIGZpZWxkX25hbWUpO1xuICAgICAgICByZXR1cm4gdGhpcy50b19udW1iZXIodmFsdWUuc3BsaXQoJy4nKVsyXSk7XG4gICAgfSxcblxuICAgIHJlcXVpcmVfcmVsYXRpdmVfdHlwZTogZnVuY3Rpb24gcmVxdWlyZV9yZWxhdGl2ZV90eXBlKHR5cGUsIHZhbHVlLCBmaWVsZF9uYW1lKSB7XG4gICAgICAgIHRoaXMucmVxdWlyZV9vYmplY3RfdHlwZSgwLCB0eXBlLCB2YWx1ZSwgZmllbGRfbmFtZSk7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuXG4gICAgZ2V0X3JlbGF0aXZlX2luc3RhbmNlOiBmdW5jdGlvbiBnZXRfcmVsYXRpdmVfaW5zdGFuY2UodHlwZSwgdmFsdWUsIGZpZWxkX25hbWUpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNfZW1wdHkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXF1aXJlX29iamVjdF90eXBlKDAsIHR5cGUsIHZhbHVlLCBmaWVsZF9uYW1lKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9fbnVtYmVyKHZhbHVlLnNwbGl0KCcuJylbMl0pO1xuICAgIH0sXG5cbiAgICByZXF1aXJlX3Byb3RvY29sX3R5cGU6IGZ1bmN0aW9uIHJlcXVpcmVfcHJvdG9jb2xfdHlwZSh0eXBlLCB2YWx1ZSwgZmllbGRfbmFtZSkge1xuICAgICAgICB0aGlzLnJlcXVpcmVfb2JqZWN0X3R5cGUoMSwgdHlwZSwgdmFsdWUsIGZpZWxkX25hbWUpO1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfSxcblxuICAgIGdldF9wcm90b2NvbF9pbnN0YW5jZTogZnVuY3Rpb24gZ2V0X3Byb3RvY29sX2luc3RhbmNlKHR5cGUsIHZhbHVlLCBmaWVsZF9uYW1lKSB7XG4gICAgICAgIGlmICh0aGlzLmlzX2VtcHR5KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVxdWlyZV9vYmplY3RfdHlwZSgxLCB0eXBlLCB2YWx1ZSwgZmllbGRfbmFtZSk7XG4gICAgICAgIHJldHVybiB0aGlzLnRvX251bWJlcih2YWx1ZS5zcGxpdCgnLicpWzJdKTtcbiAgICB9LFxuXG4gICAgZ2V0X3Byb3RvY29sX3R5cGU6IGZ1bmN0aW9uIGdldF9wcm90b2NvbF90eXBlKHZhbHVlLCBmaWVsZF9uYW1lKSB7XG4gICAgICAgIGlmICh0aGlzLmlzX2VtcHR5KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVxdWlyZV9vYmplY3RfaWQodmFsdWUsIGZpZWxkX25hbWUpO1xuICAgICAgICB2YXIgdmFsdWVzID0gdmFsdWUuc3BsaXQoJy4nKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9fbnVtYmVyKHZhbHVlc1sxXSk7XG4gICAgfSxcblxuICAgIGdldF9wcm90b2NvbF90eXBlX25hbWU6IGZ1bmN0aW9uIGdldF9wcm90b2NvbF90eXBlX25hbWUodmFsdWUsIGZpZWxkX25hbWUpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNfZW1wdHkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHR5cGVfaWQgPSB0aGlzLmdldF9wcm90b2NvbF90eXBlKHZhbHVlLCBmaWVsZF9uYW1lKTtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKENoYWluVHlwZXMub2JqZWN0X3R5cGUpW3R5cGVfaWRdO1xuICAgIH0sXG5cblxuICAgIHJlcXVpcmVfaW1wbGVtZW50YXRpb25fdHlwZTogZnVuY3Rpb24gcmVxdWlyZV9pbXBsZW1lbnRhdGlvbl90eXBlKHR5cGUsIHZhbHVlLCBmaWVsZF9uYW1lKSB7XG4gICAgICAgIHRoaXMucmVxdWlyZV9vYmplY3RfdHlwZSgyLCB0eXBlLCB2YWx1ZSwgZmllbGRfbmFtZSk7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9LFxuXG4gICAgZ2V0X2ltcGxlbWVudGF0aW9uX2luc3RhbmNlOiBmdW5jdGlvbiBnZXRfaW1wbGVtZW50YXRpb25faW5zdGFuY2UodHlwZSwgdmFsdWUsIGZpZWxkX25hbWUpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNfZW1wdHkodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZXF1aXJlX29iamVjdF90eXBlKDIsIHR5cGUsIHZhbHVlLCBmaWVsZF9uYW1lKTtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9fbnVtYmVyKHZhbHVlLnNwbGl0KCcuJylbMl0pO1xuICAgIH0sXG5cbiAgICAvLyBzaWduZWQgLyB1bnNpZ25lZCBkZWNpbWFsXG4gICAgbm9fb3ZlcmZsb3c1MzogZnVuY3Rpb24gbm9fb3ZlcmZsb3c1Myh2YWx1ZSkge1xuICAgICAgICB2YXIgZmllbGRfbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogXCJcIjtcblxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICBpZiAodmFsdWUgPiBNQVhfU0FGRV9JTlQgfHwgdmFsdWUgPCBNSU5fU0FGRV9JTlQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ292ZXJmbG93ICcgKyBmaWVsZF9uYW1lICsgJyAnICsgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgIHZhciBpbnQgPSBwYXJzZUludCh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAodmFsdWUgPiBNQVhfU0FGRV9JTlQgfHwgdmFsdWUgPCBNSU5fU0FGRV9JTlQpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ292ZXJmbG93ICcgKyBmaWVsZF9uYW1lICsgJyAnICsgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChMb25nLmlzTG9uZyh2YWx1ZSkpIHtcbiAgICAgICAgICAgIC8vIHR5cGVvZiB2YWx1ZS50b0ludCgpIGlzICdudW1iZXInXG4gICAgICAgICAgICB0aGlzLm5vX292ZXJmbG93NTModmFsdWUudG9JbnQoKSwgZmllbGRfbmFtZSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgdGhyb3cgJ3Vuc3VwcG9ydGVkIHR5cGUgJyArIGZpZWxkX25hbWUgKyAnOiAoJyArICh0eXBlb2YgdmFsdWUgPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKHZhbHVlKSkgKyAnKSAnICsgdmFsdWU7XG4gICAgfSxcblxuXG4gICAgLy8gc2lnbmVkIC8gdW5zaWduZWQgd2hvbGUgbnVtYmVycyBvbmx5XG4gICAgbm9fb3ZlcmZsb3c2NDogZnVuY3Rpb24gbm9fb3ZlcmZsb3c2NCh2YWx1ZSkge1xuICAgICAgICB2YXIgZmllbGRfbmFtZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDogXCJcIjtcbiAgICAgICAgdmFyIHVuc2lnbmVkID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiBmYWxzZTtcblxuICAgICAgICAvLyBodHRwczovL2dpdGh1Yi5jb20vZGNvZGVJTy9Mb25nLmpzL2lzc3Vlcy8yMFxuICAgICAgICBpZiAoTG9uZy5pc0xvbmcodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBCaWdJbnRlZ2VyI2lzQmlnSW50ZWdlciBodHRwczovL2dpdGh1Yi5jb20vY3J5cHRvY29pbmpzL2JpZ2kvaXNzdWVzLzIwXG4gICAgICAgIGlmICh2YWx1ZS50ICE9PSB1bmRlZmluZWQgJiYgdmFsdWUucyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aGlzLm5vX292ZXJmbG93NjQodmFsdWUudG9TdHJpbmcoKSwgZmllbGRfbmFtZSwgdW5zaWduZWQpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiKSB7XG4gICAgICAgICAgICAvLyByZW1vdmUgbGVhZGluZyB6ZXJvcywgd2lsbCBjYXVzZSBhIGZhbHNlIHBvc2l0aXZlXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoL14wKy8sICcnKTtcbiAgICAgICAgICAgIC8vIHJlbW92ZSB0cmFpbGluZyB6ZXJvc1xuICAgICAgICAgICAgd2hpbGUgKC8wJC8udGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnN1YnN0cmluZygwLCB2YWx1ZS5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgvXFwuJC8udGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAvLyByZW1vdmUgdHJhaWxpbmcgZG90XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5zdWJzdHJpbmcoMCwgdmFsdWUubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsdWUgPT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IFwiMFwiO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgbG9uZ19zdHJpbmcgPSBMb25nLmZyb21TdHJpbmcodmFsdWUsIHVuc2lnbmVkKS50b1N0cmluZygpO1xuXG4gICAgICAgICAgICBpZiAobG9uZ19zdHJpbmcgIT09IHZhbHVlLnRyaW0oKSkge1xuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignb3ZlcmZsb3cgJyArIGZpZWxkX25hbWUgKyAnICcgKyB2YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgaWYgKHZhbHVlID4gTUFYX1NBRkVfSU5UIHx8IHZhbHVlIDwgTUlOX1NBRkVfSU5UKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdvdmVyZmxvdyAnICsgZmllbGRfbmFtZSArICcgJyArIHZhbHVlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRocm93ICd1bnN1cHBvcnRlZCB0eXBlICcgKyBmaWVsZF9uYW1lICsgJzogKCcgKyAodHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyA/ICd1bmRlZmluZWQnIDogX3R5cGVvZih2YWx1ZSkpICsgJykgJyArIHZhbHVlO1xuICAgIH1cbn07XG5cbm1vZHVsZS5leHBvcnRzID0gX215OyIsIlwidXNlIHN0cmljdFwiO1xuXG52YXIgX2NyZWF0ZUNsYXNzID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBkZWZpbmVQcm9wZXJ0aWVzKHRhcmdldCwgcHJvcHMpIHsgZm9yICh2YXIgaSA9IDA7IGkgPCBwcm9wcy5sZW5ndGg7IGkrKykgeyB2YXIgZGVzY3JpcHRvciA9IHByb3BzW2ldOyBkZXNjcmlwdG9yLmVudW1lcmFibGUgPSBkZXNjcmlwdG9yLmVudW1lcmFibGUgfHwgZmFsc2U7IGRlc2NyaXB0b3IuY29uZmlndXJhYmxlID0gdHJ1ZTsgaWYgKFwidmFsdWVcIiBpbiBkZXNjcmlwdG9yKSBkZXNjcmlwdG9yLndyaXRhYmxlID0gdHJ1ZTsgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgZGVzY3JpcHRvci5rZXksIGRlc2NyaXB0b3IpOyB9IH0gcmV0dXJuIGZ1bmN0aW9uIChDb25zdHJ1Y3RvciwgcHJvdG9Qcm9wcywgc3RhdGljUHJvcHMpIHsgaWYgKHByb3RvUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IucHJvdG90eXBlLCBwcm90b1Byb3BzKTsgaWYgKHN0YXRpY1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLCBzdGF0aWNQcm9wcyk7IHJldHVybiBDb25zdHJ1Y3RvcjsgfTsgfSgpO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG4vKiogRXhjZXB0aW9uIG5lc3RpbmcuICAqL1xudmFyIEVycm9yV2l0aENhdXNlID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEVycm9yV2l0aENhdXNlKG1lc3NhZ2UsIGNhdXNlKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBFcnJvcldpdGhDYXVzZSk7XG5cbiAgICAgICAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZTtcbiAgICAgICAgaWYgKHR5cGVvZiBjYXVzZSAhPT0gXCJ1bmRlZmluZWRcIiAmJiBjYXVzZSAhPT0gbnVsbCA/IGNhdXNlLm1lc3NhZ2UgOiB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZSA9IFwiY2F1c2VcXHRcIiArIGNhdXNlLm1lc3NhZ2UgKyBcIlxcdFwiICsgdGhpcy5tZXNzYWdlO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFyIHN0YWNrID0gXCJcIjsgLy8obmV3IEVycm9yKS5zdGFja1xuICAgICAgICBpZiAodHlwZW9mIGNhdXNlICE9PSBcInVuZGVmaW5lZFwiICYmIGNhdXNlICE9PSBudWxsID8gY2F1c2Uuc3RhY2sgOiB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHN0YWNrID0gXCJjYXVzZWQgYnlcXG5cXHRcIiArIGNhdXNlLnN0YWNrICsgXCJcXHRcIiArIHN0YWNrO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5zdGFjayA9IHRoaXMubWVzc2FnZSArIFwiXFxuXCIgKyBzdGFjaztcbiAgICB9XG5cbiAgICBfY3JlYXRlQ2xhc3MoRXJyb3JXaXRoQ2F1c2UsIG51bGwsIFt7XG4gICAgICAgIGtleTogXCJ0aHJvd1wiLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gX3Rocm93KG1lc3NhZ2UsIGNhdXNlKSB7XG4gICAgICAgICAgICB2YXIgbXNnID0gbWVzc2FnZTtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2F1c2UgIT09IFwidW5kZWZpbmVkXCIgJiYgY2F1c2UgIT09IG51bGwgPyBjYXVzZS5tZXNzYWdlIDogdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgbXNnICs9IFwiXFx0IGNhdXNlOiBcIiArIGNhdXNlLm1lc3NhZ2UgKyBcIiBcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2F1c2UgIT09IFwidW5kZWZpbmVkXCIgJiYgY2F1c2UgIT09IG51bGwgPyBjYXVzZS5zdGFjayA6IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIG1zZyArPSBcIlxcbiBzdGFjazogXCIgKyBjYXVzZS5zdGFjayArIFwiIFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1zZyk7XG4gICAgICAgIH1cbiAgICB9XSk7XG5cbiAgICByZXR1cm4gRXJyb3JXaXRoQ2F1c2U7XG59KCk7XG5cbm1vZHVsZS5leHBvcnRzID0gRXJyb3JXaXRoQ2F1c2U7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbnZhciB0eXBlcyA9IHJlcXVpcmUoXCIuL3R5cGVzXCIpO1xudmFyIFNlcmlhbGl6ZXJJbXBsID0gcmVxdWlyZShcIi4vc2VyaWFsaXplclwiKTtcblxudmFyIHVpbnQ4ID0gdHlwZXMudWludDgsXG4gICAgdWludDE2ID0gdHlwZXMudWludDE2LFxuICAgIHVpbnQzMiA9IHR5cGVzLnVpbnQzMixcbiAgICBpbnQ2NCA9IHR5cGVzLmludDY0LFxuICAgIHVpbnQ2NCA9IHR5cGVzLnVpbnQ2NCxcbiAgICBzdHJpbmcgPSB0eXBlcy5zdHJpbmcsXG4gICAgYnl0ZXMgPSB0eXBlcy5ieXRlcyxcbiAgICBib29sID0gdHlwZXMuYm9vbCxcbiAgICBhcnJheSA9IHR5cGVzLmFycmF5LFxuICAgIGZpeGVkX2FycmF5ID0gdHlwZXMuZml4ZWRfYXJyYXksXG4gICAgcHJvdG9jb2xfaWRfdHlwZSA9IHR5cGVzLnByb3RvY29sX2lkX3R5cGUsXG4gICAgb2JqZWN0X2lkX3R5cGUgPSB0eXBlcy5vYmplY3RfaWRfdHlwZSxcbiAgICB2b3RlX2lkID0gdHlwZXMudm90ZV9pZCxcbiAgICBmdXR1cmVfZXh0ZW5zaW9ucyA9IHR5cGVzLmZ1dHVyZV9leHRlbnNpb25zLFxuICAgIHN0YXRpY192YXJpYW50ID0gdHlwZXMuc3RhdGljX3ZhcmlhbnQsXG4gICAgbWFwID0gdHlwZXMubWFwLFxuICAgIHNldCA9IHR5cGVzLnNldCxcbiAgICBwdWJsaWNfa2V5ID0gdHlwZXMucHVibGljX2tleSxcbiAgICBhZGRyZXNzID0gdHlwZXMuYWRkcmVzcyxcbiAgICB0aW1lX3BvaW50X3NlYyA9IHR5cGVzLnRpbWVfcG9pbnRfc2VjLFxuICAgIG9wdGlvbmFsID0gdHlwZXMub3B0aW9uYWwsXG4gICAgdmFyaWFudCA9IHR5cGVzLnZhcmlhbnQsXG4gICAgdmFyaWFudF9vYmplY3QgPSB0eXBlcy52YXJpYW50X29iamVjdCxcbiAgICBlbnVtZXJhdGlvbiA9IHR5cGVzLmVudW1lcmF0aW9uLFxuICAgIHNoYTI1NiA9IHR5cGVzLnNoYTI1NjtcblxuXG5mdXR1cmVfZXh0ZW5zaW9ucyA9IHR5cGVzLnZvaWQ7XG5cbi8qXG5XaGVuIHVwZGF0aW5nIGdlbmVyYXRlZCBjb2RlXG5SZXBsYWNlOiAgb3BlcmF0aW9uID0gc3RhdGljX3ZhcmlhbnQgW1xud2l0aDogICAgIG9wZXJhdGlvbi5zdF9vcGVyYXRpb25zID0gW1xuXG5EZWxldGU6XG5wdWJsaWNfa2V5ID0gbmV3IFNlcmlhbGl6ZXIoIFxuICAgIFwicHVibGljX2tleVwiXG4gICAga2V5X2RhdGE6IGJ5dGVzIDMzXG4pXG5cbiovXG4vLyBQbGFjZS1ob2xkZXIsIHRoZWlyIGFyZSBkZXBlbmRlbmNpZXMgb24gXCJvcGVyYXRpb25cIiAuLiBUaGUgZmluYWwgbGlzdCBvZlxuLy8gb3BlcmF0aW9ucyBpcyBub3QgYXZpYWxibGUgdW50aWwgdGhlIHZlcnkgZW5kIG9mIHRoZSBnZW5lcmF0ZWQgY29kZS5cbi8vIFNlZTogb3BlcmF0aW9uLnN0X29wZXJhdGlvbnMgPSAuLi5cbnZhciBvcGVyYXRpb24gPSBzdGF0aWNfdmFyaWFudCgpO1xubW9kdWxlLmV4cG9ydHNbXCJvcGVyYXRpb25cIl0gPSBvcGVyYXRpb247XG5cbi8vIEZvciBtb2R1bGUuZXhwb3J0c1xudmFyIFNlcmlhbGl6ZXIgPSBmdW5jdGlvbiBTZXJpYWxpemVyKG9wZXJhdGlvbl9uYW1lLCBzZXJpbGl6YXRpb25fdHlwZXNfb2JqZWN0KSB7XG4gICAgdmFyIHMgPSBuZXcgU2VyaWFsaXplckltcGwob3BlcmF0aW9uX25hbWUsIHNlcmlsaXphdGlvbl90eXBlc19vYmplY3QpO1xuICAgIHJldHVybiBtb2R1bGUuZXhwb3J0c1tvcGVyYXRpb25fbmFtZV0gPSBzO1xufTtcblxuLy8gQ3VzdG9tLXR5cGVzIGZvbGxvdyBHZW5lcmF0ZWQgY29kZTpcblxuLy8gIyMgIEdlbmVyYXRlZCBjb2RlIGZvbGxvd3Ncbi8vICMgcHJvZ3JhbXMvanNfb3BlcmF0aW9uX3NlcmlhbGl6ZXIgPiBucG0gaSAtZyBkZWNhZmZlaW5hdGVcbi8vICMjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbnZhciB0cmFuc2Zlcl9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcInRyYW5zZmVyX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0LFxuICAgIHByaWNlX3Blcl9rYnl0ZTogdWludDMyIH0pO1xuXG52YXIgbGltaXRfb3JkZXJfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwibGltaXRfb3JkZXJfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgbGltaXRfb3JkZXJfY2FuY2VsX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwibGltaXRfb3JkZXJfY2FuY2VsX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgY2FsbF9vcmRlcl91cGRhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJjYWxsX29yZGVyX3VwZGF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBmZWU6IHVpbnQ2NCB9KTtcblxudmFyIGZpbGxfb3JkZXJfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJmaWxsX29yZGVyX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiKTtcblxudmFyIGFjY291bnRfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiYWNjb3VudF9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgYmFzaWNfZmVlOiB1aW50NjQsXG4gICAgcHJlbWl1bV9mZWU6IHVpbnQ2NCxcbiAgICBwcmljZV9wZXJfa2J5dGU6IHVpbnQzMiB9KTtcblxudmFyIGFjY291bnRfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiYWNjb3VudF91cGRhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiBpbnQ2NCxcbiAgICBwcmljZV9wZXJfa2J5dGU6IHVpbnQzMiB9KTtcblxudmFyIGFjY291bnRfd2hpdGVsaXN0X29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiYWNjb3VudF93aGl0ZWxpc3Rfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiBpbnQ2NCB9KTtcblxudmFyIGFjY291bnRfdXBncmFkZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImFjY291bnRfdXBncmFkZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBtZW1iZXJzaGlwX2FubnVhbF9mZWU6IHVpbnQ2NCxcbiAgICBtZW1iZXJzaGlwX2xpZmV0aW1lX2ZlZTogdWludDY0IH0pO1xuXG52YXIgYWNjb3VudF90cmFuc2Zlcl9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImFjY291bnRfdHJhbnNmZXJfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciBhc3NldF9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgc3ltYm9sMzogdWludDY0LFxuICAgIHN5bWJvbDQ6IHVpbnQ2NCxcbiAgICBsb25nX3N5bWJvbDogdWludDY0LFxuICAgIHByaWNlX3Blcl9rYnl0ZTogdWludDMyIH0pO1xuXG52YXIgYXNzZXRfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0LFxuICAgIHByaWNlX3Blcl9rYnl0ZTogdWludDMyIH0pO1xuXG52YXIgYXNzZXRfdXBkYXRlX2JpdGFzc2V0X29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfdXBkYXRlX2JpdGFzc2V0X29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgYXNzZXRfdXBkYXRlX2ZlZWRfcHJvZHVjZXJzX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfdXBkYXRlX2ZlZWRfcHJvZHVjZXJzX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgYXNzZXRfaXNzdWVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9pc3N1ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBmZWU6IHVpbnQ2NCxcbiAgICBwcmljZV9wZXJfa2J5dGU6IHVpbnQzMiB9KTtcblxudmFyIGFzc2V0X3Jlc2VydmVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9yZXNlcnZlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgYXNzZXRfZnVuZF9mZWVfcG9vbF9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImFzc2V0X2Z1bmRfZmVlX3Bvb2xfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciBhc3NldF9zZXR0bGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9zZXR0bGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciBhc3NldF9nbG9iYWxfc2V0dGxlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfZ2xvYmFsX3NldHRsZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBmZWU6IHVpbnQ2NCB9KTtcblxudmFyIGFzc2V0X3B1Ymxpc2hfZmVlZF9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImFzc2V0X3B1Ymxpc2hfZmVlZF9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBmZWU6IHVpbnQ2NCB9KTtcblxudmFyIHdpdG5lc3NfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwid2l0bmVzc19jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciB3aXRuZXNzX3VwZGF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcIndpdG5lc3NfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogaW50NjQgfSk7XG5cbnZhciBwcm9wb3NhbF9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJwcm9wb3NhbF9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQsXG4gICAgcHJpY2VfcGVyX2tieXRlOiB1aW50MzIgfSk7XG5cbnZhciBwcm9wb3NhbF91cGRhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJwcm9wb3NhbF91cGRhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQsXG4gICAgcHJpY2VfcGVyX2tieXRlOiB1aW50MzIgfSk7XG5cbnZhciBwcm9wb3NhbF9kZWxldGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJwcm9wb3NhbF9kZWxldGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciB3aXRoZHJhd19wZXJtaXNzaW9uX2NyZWF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcIndpdGhkcmF3X3Blcm1pc3Npb25fY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgd2l0aGRyYXdfcGVybWlzc2lvbl91cGRhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJ3aXRoZHJhd19wZXJtaXNzaW9uX3VwZGF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBmZWU6IHVpbnQ2NCB9KTtcblxudmFyIHdpdGhkcmF3X3Blcm1pc3Npb25fY2xhaW1fb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJ3aXRoZHJhd19wZXJtaXNzaW9uX2NsYWltX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0LFxuICAgIHByaWNlX3Blcl9rYnl0ZTogdWludDMyIH0pO1xuXG52YXIgd2l0aGRyYXdfcGVybWlzc2lvbl9kZWxldGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJ3aXRoZHJhd19wZXJtaXNzaW9uX2RlbGV0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBmZWU6IHVpbnQ2NCB9KTtcblxudmFyIGNvbW1pdHRlZV9tZW1iZXJfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiY29tbWl0dGVlX21lbWJlcl9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciBjb21taXR0ZWVfbWVtYmVyX3VwZGF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImNvbW1pdHRlZV9tZW1iZXJfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgY29tbWl0dGVlX21lbWJlcl91cGRhdGVfZ2xvYmFsX3BhcmFtZXRlcnNfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJjb21taXR0ZWVfbWVtYmVyX3VwZGF0ZV9nbG9iYWxfcGFyYW1ldGVyc19vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBmZWU6IHVpbnQ2NCB9KTtcblxudmFyIHZlc3RpbmdfYmFsYW5jZV9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJ2ZXN0aW5nX2JhbGFuY2VfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgdmVzdGluZ19iYWxhbmNlX3dpdGhkcmF3X29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwidmVzdGluZ19iYWxhbmNlX3dpdGhkcmF3X29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgd29ya2VyX2NyZWF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcIndvcmtlcl9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciBjdXN0b21fb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJjdXN0b21fb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQsXG4gICAgcHJpY2VfcGVyX2tieXRlOiB1aW50MzIgfSk7XG5cbnZhciBhc3NlcnRfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NlcnRfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciBiYWxhbmNlX2NsYWltX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiYmFsYW5jZV9jbGFpbV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIik7XG5cbnZhciBvdmVycmlkZV90cmFuc2Zlcl9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcIm92ZXJyaWRlX3RyYW5zZmVyX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0LFxuICAgIHByaWNlX3Blcl9rYnl0ZTogdWludDMyIH0pO1xuXG52YXIgdHJhbnNmZXJfdG9fYmxpbmRfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJ0cmFuc2Zlcl90b19ibGluZF9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnNcIiwgeyBmZWU6IHVpbnQ2NCxcbiAgICBwcmljZV9wZXJfb3V0cHV0OiB1aW50MzIgfSk7XG5cbnZhciBibGluZF90cmFuc2Zlcl9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImJsaW5kX3RyYW5zZmVyX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0LFxuICAgIHByaWNlX3Blcl9vdXRwdXQ6IHVpbnQzMiB9KTtcblxudmFyIHRyYW5zZmVyX2Zyb21fYmxpbmRfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJ0cmFuc2Zlcl9mcm9tX2JsaW5kX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgYXNzZXRfc2V0dGxlX2NhbmNlbF9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImFzc2V0X3NldHRsZV9jYW5jZWxfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIpO1xuXG52YXIgYXNzZXRfY2xhaW1fZmVlc19vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImFzc2V0X2NsYWltX2ZlZXNfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXCIsIHsgZmVlOiB1aW50NjQgfSk7XG5cbnZhciBmYmFfZGlzdHJpYnV0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcImZiYV9kaXN0cmlidXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7fSk7XG5cbnZhciB0b3VybmFtZW50X2NyZWF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMgPSBuZXcgU2VyaWFsaXplcihcInRvdXJuYW1lbnRfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0LFxuICAgIHByaWNlX3Blcl9rYnl0ZTogdWludDMyIH0pO1xuXG52YXIgdG91cm5hbWVudF9qb2luX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwidG91cm5hbWVudF9qb2luX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVyc1wiLCB7IGZlZTogdWludDY0IH0pO1xuXG52YXIgZmVlX3BhcmFtZXRlcnMgPSBzdGF0aWNfdmFyaWFudChbdHJhbnNmZXJfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBsaW1pdF9vcmRlcl9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBsaW1pdF9vcmRlcl9jYW5jZWxfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBjYWxsX29yZGVyX3VwZGF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIGZpbGxfb3JkZXJfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBhY2NvdW50X2NyZWF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIGFjY291bnRfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYWNjb3VudF93aGl0ZWxpc3Rfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBhY2NvdW50X3VwZ3JhZGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBhY2NvdW50X3RyYW5zZmVyX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYXNzZXRfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYXNzZXRfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYXNzZXRfdXBkYXRlX2JpdGFzc2V0X29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYXNzZXRfdXBkYXRlX2ZlZWRfcHJvZHVjZXJzX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYXNzZXRfaXNzdWVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBhc3NldF9yZXNlcnZlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYXNzZXRfZnVuZF9mZWVfcG9vbF9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIGFzc2V0X3NldHRsZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIGFzc2V0X2dsb2JhbF9zZXR0bGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBhc3NldF9wdWJsaXNoX2ZlZWRfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCB3aXRuZXNzX2NyZWF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIHdpdG5lc3NfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgcHJvcG9zYWxfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgcHJvcG9zYWxfdXBkYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgcHJvcG9zYWxfZGVsZXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgd2l0aGRyYXdfcGVybWlzc2lvbl9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCB3aXRoZHJhd19wZXJtaXNzaW9uX3VwZGF0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIHdpdGhkcmF3X3Blcm1pc3Npb25fY2xhaW1fb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCB3aXRoZHJhd19wZXJtaXNzaW9uX2RlbGV0ZV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIGNvbW1pdHRlZV9tZW1iZXJfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgY29tbWl0dGVlX21lbWJlcl91cGRhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBjb21taXR0ZWVfbWVtYmVyX3VwZGF0ZV9nbG9iYWxfcGFyYW1ldGVyc19vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIHZlc3RpbmdfYmFsYW5jZV9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCB2ZXN0aW5nX2JhbGFuY2Vfd2l0aGRyYXdfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCB3b3JrZXJfY3JlYXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgY3VzdG9tX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYXNzZXJ0X29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYmFsYW5jZV9jbGFpbV9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIG92ZXJyaWRlX3RyYW5zZmVyX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgdHJhbnNmZXJfdG9fYmxpbmRfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBibGluZF90cmFuc2Zlcl9vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIHRyYW5zZmVyX2Zyb21fYmxpbmRfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCBhc3NldF9zZXR0bGVfY2FuY2VsX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgYXNzZXRfY2xhaW1fZmVlc19vcGVyYXRpb25fZmVlX3BhcmFtZXRlcnMsIGZiYV9kaXN0cmlidXRlX29wZXJhdGlvbl9mZWVfcGFyYW1ldGVycywgdG91cm5hbWVudF9jcmVhdGVfb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzLCB0b3VybmFtZW50X2pvaW5fb3BlcmF0aW9uX2ZlZV9wYXJhbWV0ZXJzXSk7XG5cbnZhciBmZWVfc2NoZWR1bGUgPSBuZXcgU2VyaWFsaXplcihcImZlZV9zY2hlZHVsZVwiLCB7IHBhcmFtZXRlcnM6IHNldChmZWVfcGFyYW1ldGVycyksXG4gICAgc2NhbGU6IHVpbnQzMiB9KTtcblxudmFyIHZvaWRfcmVzdWx0ID0gbmV3IFNlcmlhbGl6ZXIoXCJ2b2lkX3Jlc3VsdFwiKTtcblxudmFyIGFzc2V0ID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldFwiLCB7IGFtb3VudDogaW50NjQsXG4gICAgYXNzZXRfaWQ6IHByb3RvY29sX2lkX3R5cGUoXCJhc3NldFwiKSB9KTtcblxudmFyIG9wZXJhdGlvbl9yZXN1bHQgPSBzdGF0aWNfdmFyaWFudChbdm9pZF9yZXN1bHQsIG9iamVjdF9pZF90eXBlLCBhc3NldF0pO1xuXG52YXIgcHJvY2Vzc2VkX3RyYW5zYWN0aW9uID0gbmV3IFNlcmlhbGl6ZXIoXCJwcm9jZXNzZWRfdHJhbnNhY3Rpb25cIiwgeyByZWZfYmxvY2tfbnVtOiB1aW50MTYsXG4gICAgcmVmX2Jsb2NrX3ByZWZpeDogdWludDMyLFxuICAgIGV4cGlyYXRpb246IHRpbWVfcG9pbnRfc2VjLFxuICAgIG9wZXJhdGlvbnM6IGFycmF5KG9wZXJhdGlvbiksXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSxcbiAgICBzaWduYXR1cmVzOiBhcnJheShieXRlcyg2NSkpLFxuICAgIG9wZXJhdGlvbl9yZXN1bHRzOiBhcnJheShvcGVyYXRpb25fcmVzdWx0KSB9KTtcblxudmFyIHNpZ25lZF9ibG9jayA9IG5ldyBTZXJpYWxpemVyKFwic2lnbmVkX2Jsb2NrXCIsIHsgcHJldmlvdXM6IGJ5dGVzKDIwKSxcbiAgICB0aW1lc3RhbXA6IHRpbWVfcG9pbnRfc2VjLFxuICAgIHdpdG5lc3M6IHByb3RvY29sX2lkX3R5cGUoXCJ3aXRuZXNzXCIpLFxuICAgIHRyYW5zYWN0aW9uX21lcmtsZV9yb290OiBieXRlcygyMCksXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSxcbiAgICB3aXRuZXNzX3NpZ25hdHVyZTogYnl0ZXMoNjUpLFxuICAgIHRyYW5zYWN0aW9uczogYXJyYXkocHJvY2Vzc2VkX3RyYW5zYWN0aW9uKSB9KTtcblxudmFyIGJsb2NrX2hlYWRlciA9IG5ldyBTZXJpYWxpemVyKFwiYmxvY2tfaGVhZGVyXCIsIHsgcHJldmlvdXM6IGJ5dGVzKDIwKSxcbiAgICB0aW1lc3RhbXA6IHRpbWVfcG9pbnRfc2VjLFxuICAgIHdpdG5lc3M6IHByb3RvY29sX2lkX3R5cGUoXCJ3aXRuZXNzXCIpLFxuICAgIHRyYW5zYWN0aW9uX21lcmtsZV9yb290OiBieXRlcygyMCksXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIHNpZ25lZF9ibG9ja19oZWFkZXIgPSBuZXcgU2VyaWFsaXplcihcInNpZ25lZF9ibG9ja19oZWFkZXJcIiwgeyBwcmV2aW91czogYnl0ZXMoMjApLFxuICAgIHRpbWVzdGFtcDogdGltZV9wb2ludF9zZWMsXG4gICAgd2l0bmVzczogcHJvdG9jb2xfaWRfdHlwZShcIndpdG5lc3NcIiksXG4gICAgdHJhbnNhY3Rpb25fbWVya2xlX3Jvb3Q6IGJ5dGVzKDIwKSxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpLFxuICAgIHdpdG5lc3Nfc2lnbmF0dXJlOiBieXRlcyg2NSkgfSk7XG5cbnZhciBtZW1vX2RhdGEgPSBuZXcgU2VyaWFsaXplcihcIm1lbW9fZGF0YVwiLCB7IGZyb206IHB1YmxpY19rZXksXG4gICAgdG86IHB1YmxpY19rZXksXG4gICAgbm9uY2U6IHVpbnQ2NCxcbiAgICBtZXNzYWdlOiBieXRlcygpIH0pO1xuXG52YXIgdHJhbnNmZXIgPSBuZXcgU2VyaWFsaXplcihcInRyYW5zZmVyXCIsIHsgZmVlOiBhc3NldCxcbiAgICBmcm9tOiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICB0bzogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYW1vdW50OiBhc3NldCxcbiAgICBtZW1vOiBvcHRpb25hbChtZW1vX2RhdGEpLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBsaW1pdF9vcmRlcl9jcmVhdGUgPSBuZXcgU2VyaWFsaXplcihcImxpbWl0X29yZGVyX2NyZWF0ZVwiLCB7IGZlZTogYXNzZXQsXG4gICAgc2VsbGVyOiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBhbW91bnRfdG9fc2VsbDogYXNzZXQsXG4gICAgbWluX3RvX3JlY2VpdmU6IGFzc2V0LFxuICAgIGV4cGlyYXRpb246IHRpbWVfcG9pbnRfc2VjLFxuICAgIGZpbGxfb3Jfa2lsbDogYm9vbCxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgbGltaXRfb3JkZXJfY2FuY2VsID0gbmV3IFNlcmlhbGl6ZXIoXCJsaW1pdF9vcmRlcl9jYW5jZWxcIiwgeyBmZWU6IGFzc2V0LFxuICAgIGZlZV9wYXlpbmdfYWNjb3VudDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgb3JkZXI6IHByb3RvY29sX2lkX3R5cGUoXCJsaW1pdF9vcmRlclwiKSxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgY2FsbF9vcmRlcl91cGRhdGUgPSBuZXcgU2VyaWFsaXplcihcImNhbGxfb3JkZXJfdXBkYXRlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBmdW5kaW5nX2FjY291bnQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGRlbHRhX2NvbGxhdGVyYWw6IGFzc2V0LFxuICAgIGRlbHRhX2RlYnQ6IGFzc2V0LFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBmaWxsX29yZGVyID0gbmV3IFNlcmlhbGl6ZXIoXCJmaWxsX29yZGVyXCIsIHsgZmVlOiBhc3NldCxcbiAgICBvcmRlcl9pZDogb2JqZWN0X2lkX3R5cGUsXG4gICAgYWNjb3VudF9pZDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgcGF5czogYXNzZXQsXG4gICAgcmVjZWl2ZXM6IGFzc2V0IH0pO1xuXG52YXIgYXV0aG9yaXR5ID0gbmV3IFNlcmlhbGl6ZXIoXCJhdXRob3JpdHlcIiwgeyB3ZWlnaHRfdGhyZXNob2xkOiB1aW50MzIsXG4gICAgYWNjb3VudF9hdXRoczogbWFwKHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLCB1aW50MTYpLFxuICAgIGtleV9hdXRoczogbWFwKHB1YmxpY19rZXksIHVpbnQxNiksXG4gICAgYWRkcmVzc19hdXRoczogbWFwKGFkZHJlc3MsIHVpbnQxNikgfSk7XG5cbnZhciBhY2NvdW50X29wdGlvbnMgPSBuZXcgU2VyaWFsaXplcihcImFjY291bnRfb3B0aW9uc1wiLCB7IG1lbW9fa2V5OiBwdWJsaWNfa2V5LFxuICAgIHZvdGluZ19hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBudW1fd2l0bmVzczogdWludDE2LFxuICAgIG51bV9jb21taXR0ZWU6IHVpbnQxNixcbiAgICB2b3Rlczogc2V0KHZvdGVfaWQpLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBhY2NvdW50X2NyZWF0ZSA9IG5ldyBTZXJpYWxpemVyKFwiYWNjb3VudF9jcmVhdGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIHJlZ2lzdHJhcjogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgcmVmZXJyZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIHJlZmVycmVyX3BlcmNlbnQ6IHVpbnQxNixcbiAgICBuYW1lOiBzdHJpbmcsXG4gICAgb3duZXI6IGF1dGhvcml0eSxcbiAgICBhY3RpdmU6IGF1dGhvcml0eSxcbiAgICBvcHRpb25zOiBhY2NvdW50X29wdGlvbnMsXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGFjY291bnRfdXBkYXRlID0gbmV3IFNlcmlhbGl6ZXIoXCJhY2NvdW50X3VwZGF0ZVwiLCB7IGZlZTogYXNzZXQsXG4gICAgYWNjb3VudDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgb3duZXI6IG9wdGlvbmFsKGF1dGhvcml0eSksXG4gICAgYWN0aXZlOiBvcHRpb25hbChhdXRob3JpdHkpLFxuICAgIG5ld19vcHRpb25zOiBvcHRpb25hbChhY2NvdW50X29wdGlvbnMpLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBhY2NvdW50X3doaXRlbGlzdCA9IG5ldyBTZXJpYWxpemVyKFwiYWNjb3VudF93aGl0ZWxpc3RcIiwgeyBmZWU6IGFzc2V0LFxuICAgIGF1dGhvcml6aW5nX2FjY291bnQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFjY291bnRfdG9fbGlzdDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgbmV3X2xpc3Rpbmc6IHVpbnQ4LFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBhY2NvdW50X3VwZ3JhZGUgPSBuZXcgU2VyaWFsaXplcihcImFjY291bnRfdXBncmFkZVwiLCB7IGZlZTogYXNzZXQsXG4gICAgYWNjb3VudF90b191cGdyYWRlOiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICB1cGdyYWRlX3RvX2xpZmV0aW1lX21lbWJlcjogYm9vbCxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgYWNjb3VudF90cmFuc2ZlciA9IG5ldyBTZXJpYWxpemVyKFwiYWNjb3VudF90cmFuc2ZlclwiLCB7IGZlZTogYXNzZXQsXG4gICAgYWNjb3VudF9pZDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgbmV3X293bmVyOiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgcHJpY2UgPSBuZXcgU2VyaWFsaXplcihcInByaWNlXCIsIHsgYmFzZTogYXNzZXQsXG4gICAgcXVvdGU6IGFzc2V0IH0pO1xuXG52YXIgYXNzZXRfb3B0aW9ucyA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfb3B0aW9uc1wiLCB7IG1heF9zdXBwbHk6IGludDY0LFxuICAgIG1hcmtldF9mZWVfcGVyY2VudDogdWludDE2LFxuICAgIG1heF9tYXJrZXRfZmVlOiBpbnQ2NCxcbiAgICBpc3N1ZXJfcGVybWlzc2lvbnM6IHVpbnQxNixcbiAgICBmbGFnczogdWludDE2LFxuICAgIGNvcmVfZXhjaGFuZ2VfcmF0ZTogcHJpY2UsXG4gICAgd2hpdGVsaXN0X2F1dGhvcml0aWVzOiBzZXQocHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIikpLFxuICAgIGJsYWNrbGlzdF9hdXRob3JpdGllczogc2V0KHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpKSxcbiAgICB3aGl0ZWxpc3RfbWFya2V0czogc2V0KHByb3RvY29sX2lkX3R5cGUoXCJhc3NldFwiKSksXG4gICAgYmxhY2tsaXN0X21hcmtldHM6IHNldChwcm90b2NvbF9pZF90eXBlKFwiYXNzZXRcIikpLFxuICAgIGRlc2NyaXB0aW9uOiBzdHJpbmcsXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGJpdGFzc2V0X29wdGlvbnMgPSBuZXcgU2VyaWFsaXplcihcImJpdGFzc2V0X29wdGlvbnNcIiwgeyBmZWVkX2xpZmV0aW1lX3NlYzogdWludDMyLFxuICAgIG1pbmltdW1fZmVlZHM6IHVpbnQ4LFxuICAgIGZvcmNlX3NldHRsZW1lbnRfZGVsYXlfc2VjOiB1aW50MzIsXG4gICAgZm9yY2Vfc2V0dGxlbWVudF9vZmZzZXRfcGVyY2VudDogdWludDE2LFxuICAgIG1heGltdW1fZm9yY2Vfc2V0dGxlbWVudF92b2x1bWU6IHVpbnQxNixcbiAgICBzaG9ydF9iYWNraW5nX2Fzc2V0OiBwcm90b2NvbF9pZF90eXBlKFwiYXNzZXRcIiksXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGFzc2V0X2NyZWF0ZSA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfY3JlYXRlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBpc3N1ZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIHN5bWJvbDogc3RyaW5nLFxuICAgIHByZWNpc2lvbjogdWludDgsXG4gICAgY29tbW9uX29wdGlvbnM6IGFzc2V0X29wdGlvbnMsXG4gICAgYml0YXNzZXRfb3B0czogb3B0aW9uYWwoYml0YXNzZXRfb3B0aW9ucyksXG4gICAgaXNfcHJlZGljdGlvbl9tYXJrZXQ6IGJvb2wsXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGFzc2V0X3VwZGF0ZSA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfdXBkYXRlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBpc3N1ZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFzc2V0X3RvX3VwZGF0ZTogcHJvdG9jb2xfaWRfdHlwZShcImFzc2V0XCIpLFxuICAgIG5ld19pc3N1ZXI6IG9wdGlvbmFsKHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpKSxcbiAgICBuZXdfb3B0aW9uczogYXNzZXRfb3B0aW9ucyxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgYXNzZXRfdXBkYXRlX2JpdGFzc2V0ID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF91cGRhdGVfYml0YXNzZXRcIiwgeyBmZWU6IGFzc2V0LFxuICAgIGlzc3VlcjogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYXNzZXRfdG9fdXBkYXRlOiBwcm90b2NvbF9pZF90eXBlKFwiYXNzZXRcIiksXG4gICAgbmV3X29wdGlvbnM6IGJpdGFzc2V0X29wdGlvbnMsXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGFzc2V0X3VwZGF0ZV9mZWVkX3Byb2R1Y2VycyA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfdXBkYXRlX2ZlZWRfcHJvZHVjZXJzXCIsIHsgZmVlOiBhc3NldCxcbiAgICBpc3N1ZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFzc2V0X3RvX3VwZGF0ZTogcHJvdG9jb2xfaWRfdHlwZShcImFzc2V0XCIpLFxuICAgIG5ld19mZWVkX3Byb2R1Y2Vyczogc2V0KHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpKSxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgYXNzZXRfaXNzdWUgPSBuZXcgU2VyaWFsaXplcihcImFzc2V0X2lzc3VlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBpc3N1ZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFzc2V0X3RvX2lzc3VlOiBhc3NldCxcbiAgICBpc3N1ZV90b19hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBtZW1vOiBvcHRpb25hbChtZW1vX2RhdGEpLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBhc3NldF9yZXNlcnZlID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9yZXNlcnZlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBwYXllcjogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYW1vdW50X3RvX3Jlc2VydmU6IGFzc2V0LFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBhc3NldF9mdW5kX2ZlZV9wb29sID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9mdW5kX2ZlZV9wb29sXCIsIHsgZmVlOiBhc3NldCxcbiAgICBmcm9tX2FjY291bnQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFzc2V0X2lkOiBwcm90b2NvbF9pZF90eXBlKFwiYXNzZXRcIiksXG4gICAgYW1vdW50OiBpbnQ2NCxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgYXNzZXRfc2V0dGxlID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9zZXR0bGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIGFjY291bnQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFtb3VudDogYXNzZXQsXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGFzc2V0X2dsb2JhbF9zZXR0bGUgPSBuZXcgU2VyaWFsaXplcihcImFzc2V0X2dsb2JhbF9zZXR0bGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIGlzc3VlcjogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYXNzZXRfdG9fc2V0dGxlOiBwcm90b2NvbF9pZF90eXBlKFwiYXNzZXRcIiksXG4gICAgc2V0dGxlX3ByaWNlOiBwcmljZSxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgcHJpY2VfZmVlZCA9IG5ldyBTZXJpYWxpemVyKFwicHJpY2VfZmVlZFwiLCB7IHNldHRsZW1lbnRfcHJpY2U6IHByaWNlLFxuICAgIG1haW50ZW5hbmNlX2NvbGxhdGVyYWxfcmF0aW86IHVpbnQxNixcbiAgICBtYXhpbXVtX3Nob3J0X3NxdWVlemVfcmF0aW86IHVpbnQxNixcbiAgICBjb3JlX2V4Y2hhbmdlX3JhdGU6IHByaWNlIH0pO1xuXG52YXIgYXNzZXRfcHVibGlzaF9mZWVkID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9wdWJsaXNoX2ZlZWRcIiwgeyBmZWU6IGFzc2V0LFxuICAgIHB1Ymxpc2hlcjogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYXNzZXRfaWQ6IHByb3RvY29sX2lkX3R5cGUoXCJhc3NldFwiKSxcbiAgICBmZWVkOiBwcmljZV9mZWVkLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciB3aXRuZXNzX2NyZWF0ZSA9IG5ldyBTZXJpYWxpemVyKFwid2l0bmVzc19jcmVhdGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIHdpdG5lc3NfYWNjb3VudDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgdXJsOiBzdHJpbmcsXG4gICAgYmxvY2tfc2lnbmluZ19rZXk6IHB1YmxpY19rZXkgfSk7XG5cbnZhciB3aXRuZXNzX3VwZGF0ZSA9IG5ldyBTZXJpYWxpemVyKFwid2l0bmVzc191cGRhdGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIHdpdG5lc3M6IHByb3RvY29sX2lkX3R5cGUoXCJ3aXRuZXNzXCIpLFxuICAgIHdpdG5lc3NfYWNjb3VudDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgbmV3X3VybDogb3B0aW9uYWwoc3RyaW5nKSxcbiAgICBuZXdfc2lnbmluZ19rZXk6IG9wdGlvbmFsKHB1YmxpY19rZXkpIH0pO1xuXG52YXIgb3Bfd3JhcHBlciA9IG5ldyBTZXJpYWxpemVyKFwib3Bfd3JhcHBlclwiLCB7IG9wOiBvcGVyYXRpb24gfSk7XG5cbnZhciBwcm9wb3NhbF9jcmVhdGUgPSBuZXcgU2VyaWFsaXplcihcInByb3Bvc2FsX2NyZWF0ZVwiLCB7IGZlZTogYXNzZXQsXG4gICAgZmVlX3BheWluZ19hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBleHBpcmF0aW9uX3RpbWU6IHRpbWVfcG9pbnRfc2VjLFxuICAgIHByb3Bvc2VkX29wczogYXJyYXkob3Bfd3JhcHBlciksXG4gICAgcmV2aWV3X3BlcmlvZF9zZWNvbmRzOiBvcHRpb25hbCh1aW50MzIpLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBwcm9wb3NhbF91cGRhdGUgPSBuZXcgU2VyaWFsaXplcihcInByb3Bvc2FsX3VwZGF0ZVwiLCB7IGZlZTogYXNzZXQsXG4gICAgZmVlX3BheWluZ19hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBwcm9wb3NhbDogcHJvdG9jb2xfaWRfdHlwZShcInByb3Bvc2FsXCIpLFxuICAgIGFjdGl2ZV9hcHByb3ZhbHNfdG9fYWRkOiBzZXQocHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIikpLFxuICAgIGFjdGl2ZV9hcHByb3ZhbHNfdG9fcmVtb3ZlOiBzZXQocHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIikpLFxuICAgIG93bmVyX2FwcHJvdmFsc190b19hZGQ6IHNldChwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSksXG4gICAgb3duZXJfYXBwcm92YWxzX3RvX3JlbW92ZTogc2V0KHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpKSxcbiAgICBrZXlfYXBwcm92YWxzX3RvX2FkZDogc2V0KHB1YmxpY19rZXkpLFxuICAgIGtleV9hcHByb3ZhbHNfdG9fcmVtb3ZlOiBzZXQocHVibGljX2tleSksXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIHByb3Bvc2FsX2RlbGV0ZSA9IG5ldyBTZXJpYWxpemVyKFwicHJvcG9zYWxfZGVsZXRlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBmZWVfcGF5aW5nX2FjY291bnQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIHVzaW5nX293bmVyX2F1dGhvcml0eTogYm9vbCxcbiAgICBwcm9wb3NhbDogcHJvdG9jb2xfaWRfdHlwZShcInByb3Bvc2FsXCIpLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciB3aXRoZHJhd19wZXJtaXNzaW9uX2NyZWF0ZSA9IG5ldyBTZXJpYWxpemVyKFwid2l0aGRyYXdfcGVybWlzc2lvbl9jcmVhdGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIHdpdGhkcmF3X2Zyb21fYWNjb3VudDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYXV0aG9yaXplZF9hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICB3aXRoZHJhd2FsX2xpbWl0OiBhc3NldCxcbiAgICB3aXRoZHJhd2FsX3BlcmlvZF9zZWM6IHVpbnQzMixcbiAgICBwZXJpb2RzX3VudGlsX2V4cGlyYXRpb246IHVpbnQzMixcbiAgICBwZXJpb2Rfc3RhcnRfdGltZTogdGltZV9wb2ludF9zZWMgfSk7XG5cbnZhciB3aXRoZHJhd19wZXJtaXNzaW9uX3VwZGF0ZSA9IG5ldyBTZXJpYWxpemVyKFwid2l0aGRyYXdfcGVybWlzc2lvbl91cGRhdGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIHdpdGhkcmF3X2Zyb21fYWNjb3VudDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYXV0aG9yaXplZF9hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBwZXJtaXNzaW9uX3RvX3VwZGF0ZTogcHJvdG9jb2xfaWRfdHlwZShcIndpdGhkcmF3X3Blcm1pc3Npb25cIiksXG4gICAgd2l0aGRyYXdhbF9saW1pdDogYXNzZXQsXG4gICAgd2l0aGRyYXdhbF9wZXJpb2Rfc2VjOiB1aW50MzIsXG4gICAgcGVyaW9kX3N0YXJ0X3RpbWU6IHRpbWVfcG9pbnRfc2VjLFxuICAgIHBlcmlvZHNfdW50aWxfZXhwaXJhdGlvbjogdWludDMyIH0pO1xuXG52YXIgd2l0aGRyYXdfcGVybWlzc2lvbl9jbGFpbSA9IG5ldyBTZXJpYWxpemVyKFwid2l0aGRyYXdfcGVybWlzc2lvbl9jbGFpbVwiLCB7IGZlZTogYXNzZXQsXG4gICAgd2l0aGRyYXdfcGVybWlzc2lvbjogcHJvdG9jb2xfaWRfdHlwZShcIndpdGhkcmF3X3Blcm1pc3Npb25cIiksXG4gICAgd2l0aGRyYXdfZnJvbV9hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICB3aXRoZHJhd190b19hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBhbW91bnRfdG9fd2l0aGRyYXc6IGFzc2V0LFxuICAgIG1lbW86IG9wdGlvbmFsKG1lbW9fZGF0YSkgfSk7XG5cbnZhciB3aXRoZHJhd19wZXJtaXNzaW9uX2RlbGV0ZSA9IG5ldyBTZXJpYWxpemVyKFwid2l0aGRyYXdfcGVybWlzc2lvbl9kZWxldGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIHdpdGhkcmF3X2Zyb21fYWNjb3VudDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYXV0aG9yaXplZF9hY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICB3aXRoZHJhd2FsX3Blcm1pc3Npb246IHByb3RvY29sX2lkX3R5cGUoXCJ3aXRoZHJhd19wZXJtaXNzaW9uXCIpIH0pO1xuXG52YXIgY29tbWl0dGVlX21lbWJlcl9jcmVhdGUgPSBuZXcgU2VyaWFsaXplcihcImNvbW1pdHRlZV9tZW1iZXJfY3JlYXRlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBjb21taXR0ZWVfbWVtYmVyX2FjY291bnQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIHVybDogc3RyaW5nIH0pO1xuXG52YXIgY29tbWl0dGVlX21lbWJlcl91cGRhdGUgPSBuZXcgU2VyaWFsaXplcihcImNvbW1pdHRlZV9tZW1iZXJfdXBkYXRlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBjb21taXR0ZWVfbWVtYmVyOiBwcm90b2NvbF9pZF90eXBlKFwiY29tbWl0dGVlX21lbWJlclwiKSxcbiAgICBjb21taXR0ZWVfbWVtYmVyX2FjY291bnQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIG5ld191cmw6IG9wdGlvbmFsKHN0cmluZykgfSk7XG5cbnZhciBjaGFpbl9wYXJhbWV0ZXJzID0gbmV3IFNlcmlhbGl6ZXIoXCJjaGFpbl9wYXJhbWV0ZXJzXCIsIHsgY3VycmVudF9mZWVzOiBmZWVfc2NoZWR1bGUsXG4gICAgYmxvY2tfaW50ZXJ2YWw6IHVpbnQ4LFxuICAgIG1haW50ZW5hbmNlX2ludGVydmFsOiB1aW50MzIsXG4gICAgbWFpbnRlbmFuY2Vfc2tpcF9zbG90czogdWludDgsXG4gICAgY29tbWl0dGVlX3Byb3Bvc2FsX3Jldmlld19wZXJpb2Q6IHVpbnQzMixcbiAgICBtYXhpbXVtX3RyYW5zYWN0aW9uX3NpemU6IHVpbnQzMixcbiAgICBtYXhpbXVtX2Jsb2NrX3NpemU6IHVpbnQzMixcbiAgICBtYXhpbXVtX3RpbWVfdW50aWxfZXhwaXJhdGlvbjogdWludDMyLFxuICAgIG1heGltdW1fcHJvcG9zYWxfbGlmZXRpbWU6IHVpbnQzMixcbiAgICBtYXhpbXVtX2Fzc2V0X3doaXRlbGlzdF9hdXRob3JpdGllczogdWludDgsXG4gICAgbWF4aW11bV9hc3NldF9mZWVkX3B1Ymxpc2hlcnM6IHVpbnQ4LFxuICAgIG1heGltdW1fd2l0bmVzc19jb3VudDogdWludDE2LFxuICAgIG1heGltdW1fY29tbWl0dGVlX2NvdW50OiB1aW50MTYsXG4gICAgbWF4aW11bV9hdXRob3JpdHlfbWVtYmVyc2hpcDogdWludDE2LFxuICAgIHJlc2VydmVfcGVyY2VudF9vZl9mZWU6IHVpbnQxNixcbiAgICBuZXR3b3JrX3BlcmNlbnRfb2ZfZmVlOiB1aW50MTYsXG4gICAgbGlmZXRpbWVfcmVmZXJyZXJfcGVyY2VudF9vZl9mZWU6IHVpbnQxNixcbiAgICBjYXNoYmFja192ZXN0aW5nX3BlcmlvZF9zZWNvbmRzOiB1aW50MzIsXG4gICAgY2FzaGJhY2tfdmVzdGluZ190aHJlc2hvbGQ6IGludDY0LFxuICAgIGNvdW50X25vbl9tZW1iZXJfdm90ZXM6IGJvb2wsXG4gICAgYWxsb3dfbm9uX21lbWJlcl93aGl0ZWxpc3RzOiBib29sLFxuICAgIHdpdG5lc3NfcGF5X3Blcl9ibG9jazogaW50NjQsXG4gICAgd29ya2VyX2J1ZGdldF9wZXJfZGF5OiBpbnQ2NCxcbiAgICBtYXhfcHJlZGljYXRlX29wY29kZTogdWludDE2LFxuICAgIGZlZV9saXF1aWRhdGlvbl90aHJlc2hvbGQ6IGludDY0LFxuICAgIGFjY291bnRzX3Blcl9mZWVfc2NhbGU6IHVpbnQxNixcbiAgICBhY2NvdW50X2ZlZV9zY2FsZV9iaXRzaGlmdHM6IHVpbnQ4LFxuICAgIG1heF9hdXRob3JpdHlfZGVwdGg6IHVpbnQ4LFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBjb21taXR0ZWVfbWVtYmVyX3VwZGF0ZV9nbG9iYWxfcGFyYW1ldGVycyA9IG5ldyBTZXJpYWxpemVyKFwiY29tbWl0dGVlX21lbWJlcl91cGRhdGVfZ2xvYmFsX3BhcmFtZXRlcnNcIiwgeyBmZWU6IGFzc2V0LFxuICAgIG5ld19wYXJhbWV0ZXJzOiBjaGFpbl9wYXJhbWV0ZXJzIH0pO1xuXG52YXIgbGluZWFyX3Zlc3RpbmdfcG9saWN5X2luaXRpYWxpemVyID0gbmV3IFNlcmlhbGl6ZXIoXCJsaW5lYXJfdmVzdGluZ19wb2xpY3lfaW5pdGlhbGl6ZXJcIiwgeyBiZWdpbl90aW1lc3RhbXA6IHRpbWVfcG9pbnRfc2VjLFxuICAgIHZlc3RpbmdfY2xpZmZfc2Vjb25kczogdWludDMyLFxuICAgIHZlc3RpbmdfZHVyYXRpb25fc2Vjb25kczogdWludDMyIH0pO1xuXG52YXIgY2RkX3Zlc3RpbmdfcG9saWN5X2luaXRpYWxpemVyID0gbmV3IFNlcmlhbGl6ZXIoXCJjZGRfdmVzdGluZ19wb2xpY3lfaW5pdGlhbGl6ZXJcIiwgeyBzdGFydF9jbGFpbTogdGltZV9wb2ludF9zZWMsXG4gICAgdmVzdGluZ19zZWNvbmRzOiB1aW50MzIgfSk7XG5cbnZhciB2ZXN0aW5nX3BvbGljeV9pbml0aWFsaXplciA9IHN0YXRpY192YXJpYW50KFtsaW5lYXJfdmVzdGluZ19wb2xpY3lfaW5pdGlhbGl6ZXIsIGNkZF92ZXN0aW5nX3BvbGljeV9pbml0aWFsaXplcl0pO1xuXG52YXIgdmVzdGluZ19iYWxhbmNlX2NyZWF0ZSA9IG5ldyBTZXJpYWxpemVyKFwidmVzdGluZ19iYWxhbmNlX2NyZWF0ZVwiLCB7IGZlZTogYXNzZXQsXG4gICAgY3JlYXRvcjogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgb3duZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFtb3VudDogYXNzZXQsXG4gICAgcG9saWN5OiB2ZXN0aW5nX3BvbGljeV9pbml0aWFsaXplciB9KTtcblxudmFyIHZlc3RpbmdfYmFsYW5jZV93aXRoZHJhdyA9IG5ldyBTZXJpYWxpemVyKFwidmVzdGluZ19iYWxhbmNlX3dpdGhkcmF3XCIsIHsgZmVlOiBhc3NldCxcbiAgICB2ZXN0aW5nX2JhbGFuY2U6IHByb3RvY29sX2lkX3R5cGUoXCJ2ZXN0aW5nX2JhbGFuY2VcIiksXG4gICAgb3duZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFtb3VudDogYXNzZXQgfSk7XG5cbnZhciByZWZ1bmRfd29ya2VyX2luaXRpYWxpemVyID0gbmV3IFNlcmlhbGl6ZXIoXCJyZWZ1bmRfd29ya2VyX2luaXRpYWxpemVyXCIpO1xuXG52YXIgdmVzdGluZ19iYWxhbmNlX3dvcmtlcl9pbml0aWFsaXplciA9IG5ldyBTZXJpYWxpemVyKFwidmVzdGluZ19iYWxhbmNlX3dvcmtlcl9pbml0aWFsaXplclwiLCB7IHBheV92ZXN0aW5nX3BlcmlvZF9kYXlzOiB1aW50MTYgfSk7XG5cbnZhciBidXJuX3dvcmtlcl9pbml0aWFsaXplciA9IG5ldyBTZXJpYWxpemVyKFwiYnVybl93b3JrZXJfaW5pdGlhbGl6ZXJcIik7XG5cbnZhciB3b3JrZXJfaW5pdGlhbGl6ZXIgPSBzdGF0aWNfdmFyaWFudChbcmVmdW5kX3dvcmtlcl9pbml0aWFsaXplciwgdmVzdGluZ19iYWxhbmNlX3dvcmtlcl9pbml0aWFsaXplciwgYnVybl93b3JrZXJfaW5pdGlhbGl6ZXJdKTtcblxudmFyIHdvcmtlcl9jcmVhdGUgPSBuZXcgU2VyaWFsaXplcihcIndvcmtlcl9jcmVhdGVcIiwgeyBmZWU6IGFzc2V0LFxuICAgIG93bmVyOiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICB3b3JrX2JlZ2luX2RhdGU6IHRpbWVfcG9pbnRfc2VjLFxuICAgIHdvcmtfZW5kX2RhdGU6IHRpbWVfcG9pbnRfc2VjLFxuICAgIGRhaWx5X3BheTogaW50NjQsXG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHVybDogc3RyaW5nLFxuICAgIGluaXRpYWxpemVyOiB3b3JrZXJfaW5pdGlhbGl6ZXIgfSk7XG5cbnZhciBjdXN0b20gPSBuZXcgU2VyaWFsaXplcihcImN1c3RvbVwiLCB7IGZlZTogYXNzZXQsXG4gICAgcGF5ZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIHJlcXVpcmVkX2F1dGhzOiBzZXQocHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIikpLFxuICAgIGlkOiB1aW50MTYsXG4gICAgZGF0YTogYnl0ZXMoKSB9KTtcblxudmFyIGFjY291bnRfbmFtZV9lcV9saXRfcHJlZGljYXRlID0gbmV3IFNlcmlhbGl6ZXIoXCJhY2NvdW50X25hbWVfZXFfbGl0X3ByZWRpY2F0ZVwiLCB7IGFjY291bnRfaWQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIG5hbWU6IHN0cmluZyB9KTtcblxudmFyIGFzc2V0X3N5bWJvbF9lcV9saXRfcHJlZGljYXRlID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9zeW1ib2xfZXFfbGl0X3ByZWRpY2F0ZVwiLCB7IGFzc2V0X2lkOiBwcm90b2NvbF9pZF90eXBlKFwiYXNzZXRcIiksXG4gICAgc3ltYm9sOiBzdHJpbmcgfSk7XG5cbnZhciBibG9ja19pZF9wcmVkaWNhdGUgPSBuZXcgU2VyaWFsaXplcihcImJsb2NrX2lkX3ByZWRpY2F0ZVwiLCB7IGlkOiBieXRlcygyMCkgfSk7XG5cbnZhciBwcmVkaWNhdGUgPSBzdGF0aWNfdmFyaWFudChbYWNjb3VudF9uYW1lX2VxX2xpdF9wcmVkaWNhdGUsIGFzc2V0X3N5bWJvbF9lcV9saXRfcHJlZGljYXRlLCBibG9ja19pZF9wcmVkaWNhdGVdKTtcblxudmFyIGFzc2VydCA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXJ0XCIsIHsgZmVlOiBhc3NldCxcbiAgICBmZWVfcGF5aW5nX2FjY291bnQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIHByZWRpY2F0ZXM6IGFycmF5KHByZWRpY2F0ZSksXG4gICAgcmVxdWlyZWRfYXV0aHM6IHNldChwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSksXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGJhbGFuY2VfY2xhaW0gPSBuZXcgU2VyaWFsaXplcihcImJhbGFuY2VfY2xhaW1cIiwgeyBmZWU6IGFzc2V0LFxuICAgIGRlcG9zaXRfdG9fYWNjb3VudDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYmFsYW5jZV90b19jbGFpbTogcHJvdG9jb2xfaWRfdHlwZShcImJhbGFuY2VcIiksXG4gICAgYmFsYW5jZV9vd25lcl9rZXk6IHB1YmxpY19rZXksXG4gICAgdG90YWxfY2xhaW1lZDogYXNzZXQgfSk7XG5cbnZhciBvdmVycmlkZV90cmFuc2ZlciA9IG5ldyBTZXJpYWxpemVyKFwib3ZlcnJpZGVfdHJhbnNmZXJcIiwgeyBmZWU6IGFzc2V0LFxuICAgIGlzc3VlcjogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgZnJvbTogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgdG86IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFtb3VudDogYXNzZXQsXG4gICAgbWVtbzogb3B0aW9uYWwobWVtb19kYXRhKSxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG52YXIgc3RlYWx0aF9jb25maXJtYXRpb24gPSBuZXcgU2VyaWFsaXplcihcInN0ZWFsdGhfY29uZmlybWF0aW9uXCIsIHsgb25lX3RpbWVfa2V5OiBwdWJsaWNfa2V5LFxuICAgIHRvOiBvcHRpb25hbChwdWJsaWNfa2V5KSxcbiAgICBlbmNyeXB0ZWRfbWVtbzogYnl0ZXMoKSB9KTtcblxudmFyIGJsaW5kX291dHB1dCA9IG5ldyBTZXJpYWxpemVyKFwiYmxpbmRfb3V0cHV0XCIsIHsgY29tbWl0bWVudDogYnl0ZXMoMzMpLFxuICAgIHJhbmdlX3Byb29mOiBieXRlcygpLFxuICAgIG93bmVyOiBhdXRob3JpdHksXG4gICAgc3RlYWx0aF9tZW1vOiBvcHRpb25hbChzdGVhbHRoX2NvbmZpcm1hdGlvbikgfSk7XG5cbnZhciB0cmFuc2Zlcl90b19ibGluZCA9IG5ldyBTZXJpYWxpemVyKFwidHJhbnNmZXJfdG9fYmxpbmRcIiwgeyBmZWU6IGFzc2V0LFxuICAgIGFtb3VudDogYXNzZXQsXG4gICAgZnJvbTogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYmxpbmRpbmdfZmFjdG9yOiBieXRlcygzMiksXG4gICAgb3V0cHV0czogYXJyYXkoYmxpbmRfb3V0cHV0KSB9KTtcblxudmFyIGJsaW5kX2lucHV0ID0gbmV3IFNlcmlhbGl6ZXIoXCJibGluZF9pbnB1dFwiLCB7IGNvbW1pdG1lbnQ6IGJ5dGVzKDMzKSxcbiAgICBvd25lcjogYXV0aG9yaXR5IH0pO1xuXG52YXIgYmxpbmRfdHJhbnNmZXIgPSBuZXcgU2VyaWFsaXplcihcImJsaW5kX3RyYW5zZmVyXCIsIHsgZmVlOiBhc3NldCxcbiAgICBpbnB1dHM6IGFycmF5KGJsaW5kX2lucHV0KSxcbiAgICBvdXRwdXRzOiBhcnJheShibGluZF9vdXRwdXQpIH0pO1xuXG52YXIgdHJhbnNmZXJfZnJvbV9ibGluZCA9IG5ldyBTZXJpYWxpemVyKFwidHJhbnNmZXJfZnJvbV9ibGluZFwiLCB7IGZlZTogYXNzZXQsXG4gICAgYW1vdW50OiBhc3NldCxcbiAgICB0bzogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgYmxpbmRpbmdfZmFjdG9yOiBieXRlcygzMiksXG4gICAgaW5wdXRzOiBhcnJheShibGluZF9pbnB1dCkgfSk7XG5cbnZhciBhc3NldF9zZXR0bGVfY2FuY2VsID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9zZXR0bGVfY2FuY2VsXCIsIHsgZmVlOiBhc3NldCxcbiAgICBzZXR0bGVtZW50OiBwcm90b2NvbF9pZF90eXBlKFwiZm9yY2Vfc2V0dGxlbWVudFwiKSxcbiAgICBhY2NvdW50OiBwcm90b2NvbF9pZF90eXBlKFwiYWNjb3VudFwiKSxcbiAgICBhbW91bnQ6IGFzc2V0LFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciBhc3NldF9jbGFpbV9mZWVzID0gbmV3IFNlcmlhbGl6ZXIoXCJhc3NldF9jbGFpbV9mZWVzXCIsIHsgZmVlOiBhc3NldCxcbiAgICBpc3N1ZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFtb3VudF90b19jbGFpbTogYXNzZXQsXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGZiYV9kaXN0cmlidXRlID0gbmV3IFNlcmlhbGl6ZXIoXCJmYmFfZGlzdHJpYnV0ZVwiLCB7IGZlZTogYXNzZXQsXG4gICAgYWNjb3VudF9pZDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgZmJhX2lkOiBwcm90b2NvbF9pZF90eXBlKFwiZmJhX2FjY3VtdWxhdG9yXCIpLFxuICAgIGFtb3VudDogaW50NjQgfSk7XG5cbnZhciBkaXZpZGVuZF9hc3NldF9vcHRpb25zID0gbmV3IFNlcmlhbGl6ZXIoXCJkaXZpZGVuZF9hc3NldF9vcHRpb25zXCIsIHsgbmV4dF9wYXlvdXRfdGltZTogb3B0aW9uYWwodGltZV9wb2ludF9zZWMpLFxuICAgIHBheW91dF9pbnRlcnZhbDogb3B0aW9uYWwodWludDMyKSxcbiAgICBtaW5pbXVtX2ZlZV9wZXJjZW50YWdlOiB1aW50NjQsXG4gICAgbWluaW11bV9kaXN0cmlidXRpb25faW50ZXJ2YWw6IG9wdGlvbmFsKHVpbnQzMiksXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIGFzc2V0X3VwZGF0ZV9kaXZpZGVuZCA9IG5ldyBTZXJpYWxpemVyKFwiYXNzZXRfdXBkYXRlX2RpdmlkZW5kXCIsIHsgZmVlOiBhc3NldCxcbiAgICBpc3N1ZXI6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIGFzc2V0X3RvX3VwZGF0ZTogcHJvdG9jb2xfaWRfdHlwZShcImFzc2V0XCIpLFxuICAgIG5ld19vcHRpb25zOiBkaXZpZGVuZF9hc3NldF9vcHRpb25zLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciByb2NrX3BhcGVyX3NjaXNzb3JzX2dhbWVfb3B0aW9ucyA9IG5ldyBTZXJpYWxpemVyKFwicm9ja19wYXBlcl9zY2lzc29yc19nYW1lX29wdGlvbnNcIiwgeyBpbnN1cmFuY2VfZW5hYmxlZDogYm9vbCxcbiAgICB0aW1lX3Blcl9jb21taXRfbW92ZTogdWludDMyLFxuICAgIHRpbWVfcGVyX3JldmVhbF9tb3ZlOiB1aW50MzIsXG4gICAgbnVtYmVyX29mX2dlc3R1cmVzOiB1aW50OCB9KTtcblxudmFyIGdhbWVfc3BlY2lmaWNfZGV0YWlscyA9IHN0YXRpY192YXJpYW50KFtyb2NrX3BhcGVyX3NjaXNzb3JzX2dhbWVfb3B0aW9uc10pO1xuXG52YXIgdG91cm5hbWVudF9vcHRpb25zID0gbmV3IFNlcmlhbGl6ZXIoXCJ0b3VybmFtZW50X29wdGlvbnNcIiwge1xuICAgIHR5cGVfb2ZfZ2FtZTogdWludDE2LFxuICAgIHJlZ2lzdHJhdGlvbl9kZWFkbGluZTogdGltZV9wb2ludF9zZWMsXG4gICAgbnVtYmVyX29mX3BsYXllcnM6IHVpbnQzMixcbiAgICBidXlfaW46IGFzc2V0LFxuICAgIHdoaXRlbGlzdDogc2V0KHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpKSxcbiAgICBzdGFydF90aW1lOiBvcHRpb25hbCh0aW1lX3BvaW50X3NlYyksXG4gICAgc3RhcnRfZGVsYXk6IG9wdGlvbmFsKHVpbnQzMiksXG4gICAgcm91bmRfZGVsYXk6IHVpbnQzMixcbiAgICBudW1iZXJfb2Zfd2luczogdWludDMyLFxuICAgIG1ldGE6IHZhcmlhbnRfb2JqZWN0LFxuICAgIGdhbWVfb3B0aW9uczogZ2FtZV9zcGVjaWZpY19kZXRhaWxzXG59KTtcblxudmFyIHRvdXJuYW1lbnRfY3JlYXRlID0gbmV3IFNlcmlhbGl6ZXIoXCJ0b3VybmFtZW50X2NyZWF0ZVwiLCB7IGZlZTogYXNzZXQsXG4gICAgY3JlYXRvcjogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgb3B0aW9uczogdG91cm5hbWVudF9vcHRpb25zLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucykgfSk7XG5cbnZhciB0b3VybmFtZW50X2pvaW4gPSBuZXcgU2VyaWFsaXplcihcInRvdXJuYW1lbnRfam9pblwiLCB7IGZlZTogYXNzZXQsXG4gICAgcGF5ZXJfYWNjb3VudF9pZDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgcGxheWVyX2FjY291bnRfaWQ6IHByb3RvY29sX2lkX3R5cGUoXCJhY2NvdW50XCIpLFxuICAgIHRvdXJuYW1lbnRfaWQ6IHByb3RvY29sX2lkX3R5cGUoXCJ0b3VybmFtZW50XCIpLFxuICAgIGJ1eV9pbjogYXNzZXQsXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIHJvY2tfcGFwZXJfc2Npc3NvcnNfZ2VzdHVyZSA9IGVudW1lcmF0aW9uKFtcInJvY2tcIiwgXCJwYXBlclwiLCBcInNjaXNzb3JzXCIsIFwic3BvY2tcIiwgXCJsaXphcmRcIl0pO1xuXG52YXIgcm9ja19wYXBlcl9zY2lzc29yc190aHJvd19jb21taXQgPSBuZXcgU2VyaWFsaXplcihcInJvY2tfcGFwZXJfc2Npc3NvcnNfdGhyb3dfY29tbWl0XCIsIHsgbm9uY2UxOiB1aW50NjQsXG4gICAgdGhyb3dfaGFzaDogc2hhMjU2IH0pO1xuXG52YXIgcm9ja19wYXBlcl9zY2lzc29yc190aHJvd19yZXZlYWwgPSBuZXcgU2VyaWFsaXplcihcInJvY2tfcGFwZXJfc2Npc3NvcnNfdGhyb3dfcmV2ZWFsXCIsIHsgbm9uY2UyOiB1aW50NjQsXG4gICAgZ2VzdHVyZTogcm9ja19wYXBlcl9zY2lzc29yc19nZXN0dXJlIH0pO1xuXG52YXIgZ2FtZV9zcGVjaWZpY19tb3ZlcyA9IHN0YXRpY192YXJpYW50KFtyb2NrX3BhcGVyX3NjaXNzb3JzX3Rocm93X2NvbW1pdCwgcm9ja19wYXBlcl9zY2lzc29yc190aHJvd19yZXZlYWxdKTtcblxudmFyIGdhbWVfbW92ZSA9IG5ldyBTZXJpYWxpemVyKFwiZ2FtZV9tb3ZlXCIsIHsgZmVlOiBhc3NldCxcbiAgICBnYW1lX2lkOiBwcm90b2NvbF9pZF90eXBlKFwiZ2FtZVwiKSxcbiAgICBwbGF5ZXJfYWNjb3VudF9pZDogcHJvdG9jb2xfaWRfdHlwZShcImFjY291bnRcIiksXG4gICAgbW92ZTogZ2FtZV9zcGVjaWZpY19tb3ZlcyxcbiAgICBleHRlbnNpb25zOiBzZXQoZnV0dXJlX2V4dGVuc2lvbnMpIH0pO1xuXG5vcGVyYXRpb24uc3Rfb3BlcmF0aW9ucyA9IFt0cmFuc2ZlciwgbGltaXRfb3JkZXJfY3JlYXRlLCBsaW1pdF9vcmRlcl9jYW5jZWwsIGNhbGxfb3JkZXJfdXBkYXRlLCBmaWxsX29yZGVyLCBhY2NvdW50X2NyZWF0ZSwgYWNjb3VudF91cGRhdGUsIGFjY291bnRfd2hpdGVsaXN0LCBhY2NvdW50X3VwZ3JhZGUsIGFjY291bnRfdHJhbnNmZXIsIGFzc2V0X2NyZWF0ZSwgYXNzZXRfdXBkYXRlLCBhc3NldF91cGRhdGVfYml0YXNzZXQsIGFzc2V0X3VwZGF0ZV9mZWVkX3Byb2R1Y2VycywgYXNzZXRfaXNzdWUsIGFzc2V0X3Jlc2VydmUsIGFzc2V0X2Z1bmRfZmVlX3Bvb2wsIGFzc2V0X3NldHRsZSwgYXNzZXRfZ2xvYmFsX3NldHRsZSwgYXNzZXRfcHVibGlzaF9mZWVkLCB3aXRuZXNzX2NyZWF0ZSwgd2l0bmVzc191cGRhdGUsIHByb3Bvc2FsX2NyZWF0ZSwgcHJvcG9zYWxfdXBkYXRlLCBwcm9wb3NhbF9kZWxldGUsIHdpdGhkcmF3X3Blcm1pc3Npb25fY3JlYXRlLCB3aXRoZHJhd19wZXJtaXNzaW9uX3VwZGF0ZSwgd2l0aGRyYXdfcGVybWlzc2lvbl9jbGFpbSwgd2l0aGRyYXdfcGVybWlzc2lvbl9kZWxldGUsIGNvbW1pdHRlZV9tZW1iZXJfY3JlYXRlLCBjb21taXR0ZWVfbWVtYmVyX3VwZGF0ZSwgY29tbWl0dGVlX21lbWJlcl91cGRhdGVfZ2xvYmFsX3BhcmFtZXRlcnMsIHZlc3RpbmdfYmFsYW5jZV9jcmVhdGUsIHZlc3RpbmdfYmFsYW5jZV93aXRoZHJhdywgd29ya2VyX2NyZWF0ZSwgY3VzdG9tLCBhc3NlcnQsIGJhbGFuY2VfY2xhaW0sIG92ZXJyaWRlX3RyYW5zZmVyLCB0cmFuc2Zlcl90b19ibGluZCwgYmxpbmRfdHJhbnNmZXIsIHRyYW5zZmVyX2Zyb21fYmxpbmQsIGFzc2V0X3NldHRsZV9jYW5jZWwsIGFzc2V0X2NsYWltX2ZlZXMsIGZiYV9kaXN0cmlidXRlLCB0b3VybmFtZW50X2NyZWF0ZSwgdG91cm5hbWVudF9qb2luLCBnYW1lX21vdmUsIGFzc2V0X3VwZGF0ZV9kaXZpZGVuZF07XG5cbnZhciB0cmFuc2FjdGlvbiA9IG5ldyBTZXJpYWxpemVyKFwidHJhbnNhY3Rpb25cIiwgeyByZWZfYmxvY2tfbnVtOiB1aW50MTYsXG4gICAgcmVmX2Jsb2NrX3ByZWZpeDogdWludDMyLFxuICAgIGV4cGlyYXRpb246IHRpbWVfcG9pbnRfc2VjLFxuICAgIG9wZXJhdGlvbnM6IGFycmF5KG9wZXJhdGlvbiksXG4gICAgZXh0ZW5zaW9uczogc2V0KGZ1dHVyZV9leHRlbnNpb25zKSB9KTtcblxudmFyIHNpZ25lZF90cmFuc2FjdGlvbiA9IG5ldyBTZXJpYWxpemVyKFwic2lnbmVkX3RyYW5zYWN0aW9uXCIsIHsgcmVmX2Jsb2NrX251bTogdWludDE2LFxuICAgIHJlZl9ibG9ja19wcmVmaXg6IHVpbnQzMixcbiAgICBleHBpcmF0aW9uOiB0aW1lX3BvaW50X3NlYyxcbiAgICBvcGVyYXRpb25zOiBhcnJheShvcGVyYXRpb24pLFxuICAgIGV4dGVuc2lvbnM6IHNldChmdXR1cmVfZXh0ZW5zaW9ucyksXG4gICAgc2lnbmF0dXJlczogYXJyYXkoYnl0ZXMoNjUpKSB9KTtcbi8vIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4vLyMgIEdlbmVyYXRlZCBjb2RlIGVuZFxuLy8jIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuLy8gQ3VzdG9tIFR5cGVzXG5cbnZhciBzdGVhbHRoX21lbW9fZGF0YSA9IG5ldyBTZXJpYWxpemVyKFwic3RlYWx0aF9tZW1vX2RhdGFcIiwge1xuICAgIGZyb206IG9wdGlvbmFsKHB1YmxpY19rZXkpLFxuICAgIGFtb3VudDogYXNzZXQsXG4gICAgYmxpbmRpbmdfZmFjdG9yOiBieXRlcygzMiksXG4gICAgY29tbWl0bWVudDogYnl0ZXMoMzMpLFxuICAgIGNoZWNrOiB1aW50MzJcbn0pO1xuLy8gdmFyIHN0ZWFsdGhfY29uZmlybWF0aW9uID0gbmV3IFNlcmlhbGl6ZXIoXG4vLyAgICAgXCJzdGVhbHRoX2NvbmZpcm1hdGlvblwiLCB7XG4vLyAgICAgb25lX3RpbWVfa2V5OiBwdWJsaWNfa2V5LFxuLy8gICAgIHRvOiBvcHRpb25hbCggcHVibGljX2tleSApLFxuLy8gICAgIGVuY3J5cHRlZF9tZW1vOiBzdGVhbHRoX21lbW9fZGF0YVxuLy8gfSkiLCIndXNlIHN0cmljdCc7XG5cbnZhciBfY3JlYXRlQ2xhc3MgPSBmdW5jdGlvbiAoKSB7IGZ1bmN0aW9uIGRlZmluZVByb3BlcnRpZXModGFyZ2V0LCBwcm9wcykgeyBmb3IgKHZhciBpID0gMDsgaSA8IHByb3BzLmxlbmd0aDsgaSsrKSB7IHZhciBkZXNjcmlwdG9yID0gcHJvcHNbaV07IGRlc2NyaXB0b3IuZW51bWVyYWJsZSA9IGRlc2NyaXB0b3IuZW51bWVyYWJsZSB8fCBmYWxzZTsgZGVzY3JpcHRvci5jb25maWd1cmFibGUgPSB0cnVlOyBpZiAoXCJ2YWx1ZVwiIGluIGRlc2NyaXB0b3IpIGRlc2NyaXB0b3Iud3JpdGFibGUgPSB0cnVlOyBPYmplY3QuZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBkZXNjcmlwdG9yLmtleSwgZGVzY3JpcHRvcik7IH0gfSByZXR1cm4gZnVuY3Rpb24gKENvbnN0cnVjdG9yLCBwcm90b1Byb3BzLCBzdGF0aWNQcm9wcykgeyBpZiAocHJvdG9Qcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvci5wcm90b3R5cGUsIHByb3RvUHJvcHMpOyBpZiAoc3RhdGljUHJvcHMpIGRlZmluZVByb3BlcnRpZXMoQ29uc3RydWN0b3IsIHN0YXRpY1Byb3BzKTsgcmV0dXJuIENvbnN0cnVjdG9yOyB9OyB9KCk7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBCeXRlQnVmZmVyID0gcmVxdWlyZSgnYnl0ZWJ1ZmZlcicpO1xudmFyIEVDID0gcmVxdWlyZSgnLi9lcnJvcl93aXRoX2NhdXNlJyk7XG5cbnZhciBIRVhfRFVNUCA9IHByb2Nlc3MuZW52Lm5wbV9jb25maWdfX2dyYXBoZW5lX3NlcmlhbGl6ZXJfaGV4X2R1bXA7XG5cbnZhciBTZXJpYWxpemVyID0gZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNlcmlhbGl6ZXIob3BlcmF0aW9uX25hbWUsIHR5cGVzKSB7XG4gICAgICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBTZXJpYWxpemVyKTtcblxuICAgICAgICB0aGlzLm9wZXJhdGlvbl9uYW1lID0gb3BlcmF0aW9uX25hbWU7XG4gICAgICAgIHRoaXMudHlwZXMgPSB0eXBlcztcbiAgICAgICAgaWYgKHRoaXMudHlwZXMpIHRoaXMua2V5cyA9IE9iamVjdC5rZXlzKHRoaXMudHlwZXMpO1xuXG4gICAgICAgIFNlcmlhbGl6ZXIucHJpbnREZWJ1ZyA9IHRydWU7XG4gICAgfVxuXG4gICAgX2NyZWF0ZUNsYXNzKFNlcmlhbGl6ZXIsIFt7XG4gICAgICAgIGtleTogJ2Zyb21CeXRlQnVmZmVyJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgICAgIHZhciBvYmplY3QgPSB7fTtcbiAgICAgICAgICAgIHZhciBmaWVsZCA9IG51bGw7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHZhciBpdGVyYWJsZSA9IHRoaXMua2V5cztcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgZmllbGQ7IGkgPCBpdGVyYWJsZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBmaWVsZCA9IGl0ZXJhYmxlW2ldO1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZSA9IHRoaXMudHlwZXNbZmllbGRdO1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEhFWF9EVU1QKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGUub3BlcmF0aW9uX25hbWUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcih0eXBlLm9wZXJhdGlvbl9uYW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgbzEgPSBiLm9mZnNldDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZS5mcm9tQnl0ZUJ1ZmZlcihiKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIG8yID0gYi5vZmZzZXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGIub2Zmc2V0ID0gbzE7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vYi5yZXNldCgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBfYiA9IGIuY29weShvMSwgbzIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKHRoaXMub3BlcmF0aW9uX25hbWUgKyAnLicgKyBmaWVsZCArICdcXHQnLCBfYi50b0hleCgpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBvYmplY3RbZmllbGRdID0gdHlwZS5mcm9tQnl0ZUJ1ZmZlcihiKTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFNlcmlhbGl6ZXIucHJpbnREZWJ1Zykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHJlYWRpbmcgJyArIHRoaXMub3BlcmF0aW9uX25hbWUgKyAnLicgKyBmaWVsZCArICcgaW4gZGF0YTonKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBiLnByaW50RGVidWcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IGU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIEVDLnRocm93KHRoaXMub3BlcmF0aW9uX25hbWUgKyAnLicgKyBmaWVsZCwgZXJyb3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgICAgICB9XG4gICAgfSwge1xuICAgICAgICBrZXk6ICdhcHBlbmRCeXRlQnVmZmVyJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgICAgICB2YXIgZmllbGQgPSBudWxsO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICB2YXIgaXRlcmFibGUgPSB0aGlzLmtleXM7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGZpZWxkOyBpIDwgaXRlcmFibGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZmllbGQgPSBpdGVyYWJsZVtpXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHR5cGUgPSB0aGlzLnR5cGVzW2ZpZWxkXTtcbiAgICAgICAgICAgICAgICAgICAgdHlwZS5hcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdFtmaWVsZF0pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgRUMudGhyb3codGhpcy5vcGVyYXRpb25fbmFtZSArICcuJyArIGZpZWxkICsgXCIgPSBcIiArIEpTT04uc3RyaW5naWZ5KG9iamVjdFtmaWVsZF0pLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBjaXJjdWxhciByZWZcbiAgICAgICAgICAgICAgICAgICAgRUMudGhyb3codGhpcy5vcGVyYXRpb25fbmFtZSArICcuJyArIGZpZWxkICsgXCIgPSBcIiArIG9iamVjdFtmaWVsZF0sIGVycm9yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2Zyb21PYmplY3QnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gZnJvbU9iamVjdChzZXJpYWxpemVkX29iamVjdCkge1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICAgICAgdmFyIGZpZWxkID0gbnVsbDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdmFyIGl0ZXJhYmxlID0gdGhpcy5rZXlzO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBmaWVsZDsgaSA8IGl0ZXJhYmxlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkID0gaXRlcmFibGVbaV07XG4gICAgICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdGhpcy50eXBlc1tmaWVsZF07XG4gICAgICAgICAgICAgICAgICAgIHZhciB2YWx1ZSA9IHNlcmlhbGl6ZWRfb2JqZWN0W2ZpZWxkXTtcbiAgICAgICAgICAgICAgICAgICAgLy9ERUJVRyB2YWx1ZSA9IHZhbHVlLnJlc29sdmUgaWYgdmFsdWUucmVzb2x2ZVxuICAgICAgICAgICAgICAgICAgICAvL0RFQlVHIGNvbnNvbGUubG9nKCcuLi4gdmFsdWUnLGZpZWxkLHZhbHVlKVxuICAgICAgICAgICAgICAgICAgICB2YXIgb2JqZWN0ID0gdHlwZS5mcm9tT2JqZWN0KHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0W2ZpZWxkXSA9IG9iamVjdDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIEVDLnRocm93KHRoaXMub3BlcmF0aW9uX25hbWUgKyAnLicgKyBmaWVsZCwgZXJyb3IpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAgICBAYXJnIHtib29sZWFufSBbZGVidWcudXNlX2RlZmF1bHQgPSBmYWxzZV0gLSBtb3JlIHRlbXBsYXRlIGZyaWVuZGx5XG4gICAgICAgICAgICBAYXJnIHtib29sZWFufSBbZGVidWcuYW5ub3RhdGUgPSBmYWxzZV0gLSBhZGQgdXNlci1mcmllbmRseSBpbmZvcm1hdGlvblxuICAgICAgICAqL1xuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICd0b09iamVjdCcsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiB0b09iamVjdCgpIHtcbiAgICAgICAgICAgIHZhciBzZXJpYWxpemVkX29iamVjdCA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDoge307XG4gICAgICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHsgdXNlX2RlZmF1bHQ6IGZhbHNlLCBhbm5vdGF0ZTogZmFsc2UgfTtcblxuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICAgICAgdmFyIGZpZWxkID0gbnVsbDtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnR5cGVzKSByZXR1cm4gcmVzdWx0O1xuXG4gICAgICAgICAgICAgICAgdmFyIGl0ZXJhYmxlID0gdGhpcy5rZXlzO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBmaWVsZDsgaSA8IGl0ZXJhYmxlLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkID0gaXRlcmFibGVbaV07XG4gICAgICAgICAgICAgICAgICAgIHZhciB0eXBlID0gdGhpcy50eXBlc1tmaWVsZF07XG4gICAgICAgICAgICAgICAgICAgIHZhciBvYmplY3QgPSB0eXBlLnRvT2JqZWN0KHR5cGVvZiBzZXJpYWxpemVkX29iamVjdCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBzZXJpYWxpemVkX29iamVjdCAhPT0gbnVsbCA/IHNlcmlhbGl6ZWRfb2JqZWN0W2ZpZWxkXSA6IHVuZGVmaW5lZCwgZGVidWcpO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRbZmllbGRdID0gb2JqZWN0O1xuICAgICAgICAgICAgICAgICAgICBpZiAoSEVYX0RVTVApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBiID0gbmV3IEJ5dGVCdWZmZXIoQnl0ZUJ1ZmZlci5ERUZBVUxUX0NBUEFDSVRZLCBCeXRlQnVmZmVyLkxJVFRMRV9FTkRJQU4pO1xuICAgICAgICAgICAgICAgICAgICAgICAgdHlwZS5hcHBlbmRCeXRlQnVmZmVyKGIsIHR5cGVvZiBzZXJpYWxpemVkX29iamVjdCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBzZXJpYWxpemVkX29iamVjdCAhPT0gbnVsbCA/IHNlcmlhbGl6ZWRfb2JqZWN0W2ZpZWxkXSA6IHVuZGVmaW5lZCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBiID0gYi5jb3B5KDAsIGIub2Zmc2V0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IodGhpcy5vcGVyYXRpb25fbmFtZSArICcuJyArIGZpZWxkLCBiLnRvSGV4KCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBFQy50aHJvdyh0aGlzLm9wZXJhdGlvbl9uYW1lICsgJy4nICsgZmllbGQsIGVycm9yKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKiBTb3J0IGJ5IHRoZSBmaXJzdCBlbGVtZW50IGluIGEgb3BlcmF0aW9uICovXG5cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ2NvbXBhcmUnLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gY29tcGFyZShhLCBiKSB7XG5cbiAgICAgICAgICAgIHZhciBmaXJzdF9rZXkgPSB0aGlzLmtleXNbMF07XG4gICAgICAgICAgICB2YXIgZmlyc3RfdHlwZSA9IHRoaXMudHlwZXNbZmlyc3Rfa2V5XTtcblxuICAgICAgICAgICAgdmFyIHZhbEEgPSBhW2ZpcnN0X2tleV07XG4gICAgICAgICAgICB2YXIgdmFsQiA9IGJbZmlyc3Rfa2V5XTtcblxuICAgICAgICAgICAgaWYgKGZpcnN0X3R5cGUuY29tcGFyZSkgcmV0dXJuIGZpcnN0X3R5cGUuY29tcGFyZSh2YWxBLCB2YWxCKTtcblxuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWxBID09PSBcIm51bWJlclwiICYmIHR5cGVvZiB2YWxCID09PSBcIm51bWJlclwiKSByZXR1cm4gdmFsQSAtIHZhbEI7XG5cbiAgICAgICAgICAgIHZhciBlbmNvZGluZyA9IHZvaWQgMDtcbiAgICAgICAgICAgIGlmIChCdWZmZXIuaXNCdWZmZXIodmFsQSkgJiYgQnVmZmVyLmlzQnVmZmVyKHZhbEIpKSB7XG4gICAgICAgICAgICAgICAgLy8gQSBiaW5hcnkgc3RyaW5nIGNvbXBhcmUgZG9lcyBub3Qgd29yay4gIElmIGxvY2FsZUNvbXBhcmUgaXMgd2VsbCBzdXBwb3J0ZWQgdGhhdCBjb3VsZCByZXBsYWNlIEhFWC4gIFBlcmZvcm1hbmFuY2UgaXMgdmVyeSBnb29kIHNvIGNvbXBhcmluZyBIRVggd29ya3MuXG4gICAgICAgICAgICAgICAgZW5jb2RpbmcgPSBcImhleFwiO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgc3RyQSA9IHZhbEEudG9TdHJpbmcoZW5jb2RpbmcpO1xuICAgICAgICAgICAgdmFyIHN0ckIgPSB2YWxCLnRvU3RyaW5nKGVuY29kaW5nKTtcbiAgICAgICAgICAgIHJldHVybiBzdHJBID4gc3RyQiA/IDEgOiBzdHJBIDwgc3RyQiA/IC0xIDogMDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDxoZWxwZXJfZnVuY3Rpb25zPlxuXG4gICAgfSwge1xuICAgICAgICBrZXk6ICdmcm9tSGV4JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIGZyb21IZXgoaGV4KSB7XG4gICAgICAgICAgICB2YXIgYiA9IEJ5dGVCdWZmZXIuZnJvbUhleChoZXgsIEJ5dGVCdWZmZXIuTElUVExFX0VORElBTik7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5mcm9tQnl0ZUJ1ZmZlcihiKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAnZnJvbUJ1ZmZlcicsXG4gICAgICAgIHZhbHVlOiBmdW5jdGlvbiBmcm9tQnVmZmVyKGJ1ZmZlcikge1xuICAgICAgICAgICAgdmFyIGIgPSBCeXRlQnVmZmVyLmZyb21CaW5hcnkoYnVmZmVyLnRvU3RyaW5nKFwiYmluYXJ5XCIpLCBCeXRlQnVmZmVyLkxJVFRMRV9FTkRJQU4pO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZnJvbUJ5dGVCdWZmZXIoYik7XG4gICAgICAgIH1cbiAgICB9LCB7XG4gICAgICAgIGtleTogJ3RvSGV4JyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvSGV4KG9iamVjdCkge1xuICAgICAgICAgICAgLy8gcmV0dXJuIHRoaXMudG9CdWZmZXIob2JqZWN0KS50b1N0cmluZyhcImhleFwiKVxuICAgICAgICAgICAgdmFyIGIgPSB0aGlzLnRvQnl0ZUJ1ZmZlcihvYmplY3QpO1xuICAgICAgICAgICAgcmV0dXJuIGIudG9IZXgoKTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndG9CeXRlQnVmZmVyJyxcbiAgICAgICAgdmFsdWU6IGZ1bmN0aW9uIHRvQnl0ZUJ1ZmZlcihvYmplY3QpIHtcbiAgICAgICAgICAgIHZhciBiID0gbmV3IEJ5dGVCdWZmZXIoQnl0ZUJ1ZmZlci5ERUZBVUxUX0NBUEFDSVRZLCBCeXRlQnVmZmVyLkxJVFRMRV9FTkRJQU4pO1xuICAgICAgICAgICAgdGhpcy5hcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCk7XG4gICAgICAgICAgICByZXR1cm4gYi5jb3B5KDAsIGIub2Zmc2V0KTtcbiAgICAgICAgfVxuICAgIH0sIHtcbiAgICAgICAga2V5OiAndG9CdWZmZXInLFxuICAgICAgICB2YWx1ZTogZnVuY3Rpb24gdG9CdWZmZXIob2JqZWN0KSB7XG4gICAgICAgICAgICByZXR1cm4gbmV3IEJ1ZmZlcih0aGlzLnRvQnl0ZUJ1ZmZlcihvYmplY3QpLnRvQmluYXJ5KCksICdiaW5hcnknKTtcbiAgICAgICAgfVxuICAgIH1dKTtcblxuICAgIHJldHVybiBTZXJpYWxpemVyO1xufSgpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFNlcmlhbGl6ZXI7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbi8qKiBDb25zb2xlIHByaW50IGFueSB0cmFuc2FjdGlvbiBvYmplY3Qgd2l0aCB6ZXJvIGRlZmF1bHQgdmFsdWVzLiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiB0ZW1wbGF0ZShvcCkge1xuXG4gICAgdmFyIG9iamVjdCA9IG9wLnRvT2JqZWN0KHZvaWQgMCwgeyB1c2VfZGVmYXVsdDogdHJ1ZSwgYW5ub3RhdGU6IHRydWUgfSk7XG5cbiAgICAvLyB2aXN1YWwgKHdpdGggZGVzY3JpcHRpb25zKVxuICAgIGNvbnNvbGUuZXJyb3IoSlNPTi5zdHJpbmdpZnkob2JqZWN0LCBudWxsLCA0KSk7XG5cbiAgICAvLyB1c2FibGUgaW4gYSBjb3B5LXBhc3RlXG5cbiAgICBvYmplY3QgPSBvcC50b09iamVjdCh2b2lkIDAsIHsgdXNlX2RlZmF1bHQ6IHRydWUsIGFubm90YXRlOiBmYWxzZSB9KTtcblxuICAgIC8vIGNvcHktcGFzdGUgb25lLWxpbmVlclxuICAgIGNvbnNvbGUuZXJyb3IoSlNPTi5zdHJpbmdpZnkob2JqZWN0KSk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIF9zbGljZWRUb0FycmF5ID0gZnVuY3Rpb24gKCkgeyBmdW5jdGlvbiBzbGljZUl0ZXJhdG9yKGFyciwgaSkgeyB2YXIgX2FyciA9IFtdOyB2YXIgX24gPSB0cnVlOyB2YXIgX2QgPSBmYWxzZTsgdmFyIF9lID0gdW5kZWZpbmVkOyB0cnkgeyBmb3IgKHZhciBfaSA9IGFycltTeW1ib2wuaXRlcmF0b3JdKCksIF9zOyAhKF9uID0gKF9zID0gX2kubmV4dCgpKS5kb25lKTsgX24gPSB0cnVlKSB7IF9hcnIucHVzaChfcy52YWx1ZSk7IGlmIChpICYmIF9hcnIubGVuZ3RoID09PSBpKSBicmVhazsgfSB9IGNhdGNoIChlcnIpIHsgX2QgPSB0cnVlOyBfZSA9IGVycjsgfSBmaW5hbGx5IHsgdHJ5IHsgaWYgKCFfbiAmJiBfaVtcInJldHVyblwiXSkgX2lbXCJyZXR1cm5cIl0oKTsgfSBmaW5hbGx5IHsgaWYgKF9kKSB0aHJvdyBfZTsgfSB9IHJldHVybiBfYXJyOyB9IHJldHVybiBmdW5jdGlvbiAoYXJyLCBpKSB7IGlmIChBcnJheS5pc0FycmF5KGFycikpIHsgcmV0dXJuIGFycjsgfSBlbHNlIGlmIChTeW1ib2wuaXRlcmF0b3IgaW4gT2JqZWN0KGFycikpIHsgcmV0dXJuIHNsaWNlSXRlcmF0b3IoYXJyLCBpKTsgfSBlbHNlIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBkZXN0cnVjdHVyZSBub24taXRlcmFibGUgaW5zdGFuY2VcIik7IH0gfTsgfSgpO1xuXG52YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gdHlwZW9mIG9iajsgfSA6IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7IH07XG5cbi8vIExvdy1sZXZlbCB0eXBlcyB0aGF0IG1ha2UgdXAgb3BlcmF0aW9uc1xuXG52YXIgdiA9IHJlcXVpcmUoJy4vU2VyaWFsaXplclZhbGlkYXRpb24nKTtcbnZhciBmcCA9IHJlcXVpcmUoJy4vRmFzdFBhcnNlcicpO1xuXG52YXIgQ2hhaW5UeXBlcyA9IHJlcXVpcmUoXCIuLi8uLi9jaGFpbi9zcmMvQ2hhaW5UeXBlc1wiKTtcbnZhciBPYmplY3RJZCA9IHJlcXVpcmUoXCIuLi8uLi9jaGFpbi9zcmMvT2JqZWN0SWRcIik7XG5cbnZhciBfcmVxdWlyZSA9IHJlcXVpcmUoXCIuLi8uLi9lY2NcIiksXG4gICAgUHVibGljS2V5ID0gX3JlcXVpcmUuUHVibGljS2V5LFxuICAgIEFkZHJlc3MgPSBfcmVxdWlyZS5BZGRyZXNzO1xuXG52YXIgX3JlcXVpcmUyID0gcmVxdWlyZShcInBlZXJwbGF5c2pzLXdzXCIpLFxuICAgIENoYWluQ29uZmlnID0gX3JlcXVpcmUyLkNoYWluQ29uZmlnO1xuXG52YXIgVHlwZXMgPSB7fTtcbm1vZHVsZS5leHBvcnRzID0gVHlwZXM7XG5cbnZhciBIRVhfRFVNUCA9IHByb2Nlc3MuZW52Lm5wbV9jb25maWdfX2dyYXBoZW5lX3NlcmlhbGl6ZXJfaGV4X2R1bXA7XG5cblR5cGVzLnVpbnQ4ID0ge1xuICAgIGZyb21CeXRlQnVmZmVyOiBmdW5jdGlvbiBmcm9tQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgIHJldHVybiBiLnJlYWRVaW50OCgpO1xuICAgIH0sXG4gICAgYXBwZW5kQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3QpIHtcbiAgICAgICAgdi5yZXF1aXJlX3JhbmdlKDAsIDB4RkYsIG9iamVjdCwgJ3VpbnQ4ICcgKyBvYmplY3QpO1xuICAgICAgICBiLndyaXRlVWludDgob2JqZWN0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0sXG4gICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgdi5yZXF1aXJlX3JhbmdlKDAsIDB4RkYsIG9iamVjdCwgJ3VpbnQ4ICcgKyBvYmplY3QpO1xuICAgICAgICByZXR1cm4gb2JqZWN0O1xuICAgIH0sXG4gICAgdG9PYmplY3Q6IGZ1bmN0aW9uIHRvT2JqZWN0KG9iamVjdCkge1xuICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICAgIGlmIChkZWJ1Zy51c2VfZGVmYXVsdCAmJiBvYmplY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cbiAgICAgICAgdi5yZXF1aXJlX3JhbmdlKDAsIDB4RkYsIG9iamVjdCwgJ3VpbnQ4ICcgKyBvYmplY3QpO1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQob2JqZWN0KTtcbiAgICB9XG59O1xuXG5UeXBlcy51aW50MTYgPSB7XG4gICAgZnJvbUJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgcmV0dXJuIGIucmVhZFVpbnQxNigpO1xuICAgIH0sXG4gICAgYXBwZW5kQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3QpIHtcbiAgICAgICAgdi5yZXF1aXJlX3JhbmdlKDAsIDB4RkZGRiwgb2JqZWN0LCAndWludDE2ICcgKyBvYmplY3QpO1xuICAgICAgICBiLndyaXRlVWludDE2KG9iamVjdCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9LFxuICAgIGZyb21PYmplY3Q6IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZV9yYW5nZSgwLCAweEZGRkYsIG9iamVjdCwgJ3VpbnQxNiAnICsgb2JqZWN0KTtcbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9LFxuICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgdmFyIGRlYnVnID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcblxuICAgICAgICBpZiAoZGVidWcudXNlX2RlZmF1bHQgJiYgb2JqZWN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHYucmVxdWlyZV9yYW5nZSgwLCAweEZGRkYsIG9iamVjdCwgJ3VpbnQxNiAnICsgb2JqZWN0KTtcbiAgICAgICAgcmV0dXJuIHBhcnNlSW50KG9iamVjdCk7XG4gICAgfVxufTtcblxuVHlwZXMudWludDMyID0ge1xuICAgIGZyb21CeXRlQnVmZmVyOiBmdW5jdGlvbiBmcm9tQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgIHJldHVybiBiLnJlYWRVaW50MzIoKTtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZV9yYW5nZSgwLCAweEZGRkZGRkZGLCBvYmplY3QsICd1aW50MzIgJyArIG9iamVjdCk7XG4gICAgICAgIGIud3JpdGVVaW50MzIob2JqZWN0KTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0sXG4gICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgdi5yZXF1aXJlX3JhbmdlKDAsIDB4RkZGRkZGRkYsIG9iamVjdCwgJ3VpbnQzMiAnICsgb2JqZWN0KTtcbiAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICB9LFxuICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgdmFyIGRlYnVnID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcblxuICAgICAgICBpZiAoZGVidWcudXNlX2RlZmF1bHQgJiYgb2JqZWN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHYucmVxdWlyZV9yYW5nZSgwLCAweEZGRkZGRkZGLCBvYmplY3QsICd1aW50MzIgJyArIG9iamVjdCk7XG4gICAgICAgIHJldHVybiBwYXJzZUludChvYmplY3QpO1xuICAgIH1cbn07XG5cbnZhciBNSU5fU0lHTkVEXzMyID0gLTEgKiBNYXRoLnBvdygyLCAzMSk7XG52YXIgTUFYX1NJR05FRF8zMiA9IE1hdGgucG93KDIsIDMxKSAtIDE7XG5cblR5cGVzLnZhcmludDMyID0ge1xuICAgIGZyb21CeXRlQnVmZmVyOiBmdW5jdGlvbiBmcm9tQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgIHJldHVybiBiLnJlYWRWYXJpbnQzMigpO1xuICAgIH0sXG4gICAgYXBwZW5kQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3QpIHtcbiAgICAgICAgdi5yZXF1aXJlX3JhbmdlKE1JTl9TSUdORURfMzIsIE1BWF9TSUdORURfMzIsIG9iamVjdCwgJ3VpbnQzMiAnICsgb2JqZWN0KTtcbiAgICAgICAgYi53cml0ZVZhcmludDMyKG9iamVjdCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9LFxuICAgIGZyb21PYmplY3Q6IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZV9yYW5nZShNSU5fU0lHTkVEXzMyLCBNQVhfU0lHTkVEXzMyLCBvYmplY3QsICd1aW50MzIgJyArIG9iamVjdCk7XG4gICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgfSxcbiAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgaWYgKGRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICB2LnJlcXVpcmVfcmFuZ2UoTUlOX1NJR05FRF8zMiwgTUFYX1NJR05FRF8zMiwgb2JqZWN0LCAndWludDMyICcgKyBvYmplY3QpO1xuICAgICAgICByZXR1cm4gcGFyc2VJbnQob2JqZWN0KTtcbiAgICB9XG59O1xuXG5UeXBlcy5pbnQ2NCA9IHtcbiAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICByZXR1cm4gYi5yZWFkSW50NjQoKTtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgYi53cml0ZUludDY0KHYudG9fbG9uZyhvYmplY3QpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0sXG4gICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICByZXR1cm4gdi50b19sb25nKG9iamVjdCk7XG4gICAgfSxcbiAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgaWYgKGRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gXCIwXCI7XG4gICAgICAgIH1cbiAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICByZXR1cm4gdi50b19sb25nKG9iamVjdCkudG9TdHJpbmcoKTtcbiAgICB9XG59O1xuXG5UeXBlcy51aW50NjQgPSB7XG4gICAgZnJvbUJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgcmV0dXJuIGIucmVhZFVpbnQ2NCgpO1xuICAgIH0sXG4gICAgYXBwZW5kQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3QpIHtcbiAgICAgICAgYi53cml0ZVVpbnQ2NCh2LnRvX3Vsb25nKHYudW5zaWduZWQob2JqZWN0KSkpO1xuICAgICAgICByZXR1cm47XG4gICAgfSxcbiAgICBmcm9tT2JqZWN0OiBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICByZXR1cm4gdi50b191bG9uZyh2LnVuc2lnbmVkKG9iamVjdCkpO1xuICAgIH0sXG4gICAgdG9PYmplY3Q6IGZ1bmN0aW9uIHRvT2JqZWN0KG9iamVjdCkge1xuICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICAgIGlmIChkZWJ1Zy51c2VfZGVmYXVsdCAmJiBvYmplY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiMFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2LnRvX3Vsb25nKG9iamVjdCkudG9TdHJpbmcoKTtcbiAgICB9XG59O1xuXG5UeXBlcy5zdHJpbmcgPSB7XG4gICAgZnJvbUJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgdmFyIGJfY29weTtcbiAgICAgICAgdmFyIGxlbiA9IGIucmVhZFZhcmludDMyKCk7XG4gICAgICAgIGJfY29weSA9IGIuY29weShiLm9mZnNldCwgYi5vZmZzZXQgKyBsZW4pLCBiLnNraXAobGVuKTtcbiAgICAgICAgcmV0dXJuIG5ldyBCdWZmZXIoYl9jb3B5LnRvQmluYXJ5KCksICdiaW5hcnknKTtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgYi53cml0ZVZhcmludDMyKG9iamVjdC5sZW5ndGgpO1xuICAgICAgICBiLmFwcGVuZChvYmplY3QudG9TdHJpbmcoJ2JpbmFyeScpLCAnYmluYXJ5Jyk7XG4gICAgICAgIHJldHVybjtcbiAgICB9LFxuICAgIGZyb21PYmplY3Q6IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgcmV0dXJuIG5ldyBCdWZmZXIob2JqZWN0KTtcbiAgICB9LFxuICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgdmFyIGRlYnVnID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcblxuICAgICAgICBpZiAoZGVidWcudXNlX2RlZmF1bHQgJiYgb2JqZWN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBcIlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvYmplY3QudG9TdHJpbmcoKTtcbiAgICB9XG59O1xuXG5UeXBlcy5ieXRlcyA9IGZ1bmN0aW9uIChzaXplKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZnJvbUJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgICAgIGlmIChzaXplID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICB2YXIgYl9jb3B5O1xuICAgICAgICAgICAgICAgIHZhciBsZW4gPSBiLnJlYWRWYXJpbnQzMigpO1xuICAgICAgICAgICAgICAgIGJfY29weSA9IGIuY29weShiLm9mZnNldCwgYi5vZmZzZXQgKyBsZW4pLCBiLnNraXAobGVuKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEJ1ZmZlcihiX2NvcHkudG9CaW5hcnkoKSwgJ2JpbmFyeScpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBiX2NvcHkgPSBiLmNvcHkoYi5vZmZzZXQsIGIub2Zmc2V0ICsgc2l6ZSksIGIuc2tpcChzaXplKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEJ1ZmZlcihiX2NvcHkudG9CaW5hcnkoKSwgJ2JpbmFyeScpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBhcHBlbmRCeXRlQnVmZmVyOiBmdW5jdGlvbiBhcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCkge1xuICAgICAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QgPT09IFwic3RyaW5nXCIpIG9iamVjdCA9IG5ldyBCdWZmZXIob2JqZWN0LCBcImhleFwiKTtcblxuICAgICAgICAgICAgaWYgKHNpemUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGIud3JpdGVWYXJpbnQzMihvYmplY3QubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGIuYXBwZW5kKG9iamVjdC50b1N0cmluZygnYmluYXJ5JyksICdiaW5hcnknKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSxcbiAgICAgICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgICAgIGlmIChCdWZmZXIuaXNCdWZmZXIob2JqZWN0KSkgcmV0dXJuIG9iamVjdDtcblxuICAgICAgICAgICAgcmV0dXJuIG5ldyBCdWZmZXIob2JqZWN0LCAnaGV4Jyk7XG4gICAgICAgIH0sXG4gICAgICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgICAgIGlmIChkZWJ1Zy51c2VfZGVmYXVsdCAmJiBvYmplY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHZhciB6ZXJvcyA9IGZ1bmN0aW9uIHplcm9zKG51bSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEFycmF5KG51bSkuam9pbihcIjAwXCIpO1xuICAgICAgICAgICAgICAgIH07XG4gICAgICAgICAgICAgICAgcmV0dXJuIHplcm9zKHNpemUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdC50b1N0cmluZygnaGV4Jyk7XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuVHlwZXMuYm9vbCA9IHtcbiAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICByZXR1cm4gYi5yZWFkVWludDgoKSA9PT0gMTtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIC8vIHN1cHBvcnRzIGJvb2xlYW4gb3IgaW50ZWdlclxuICAgICAgICBiLndyaXRlVWludDgoSlNPTi5wYXJzZShvYmplY3QpID8gMSA6IDApO1xuICAgICAgICByZXR1cm47XG4gICAgfSxcbiAgICBmcm9tT2JqZWN0OiBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICByZXR1cm4gSlNPTi5wYXJzZShvYmplY3QpID8gdHJ1ZSA6IGZhbHNlO1xuICAgIH0sXG4gICAgdG9PYmplY3Q6IGZ1bmN0aW9uIHRvT2JqZWN0KG9iamVjdCkge1xuICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICAgIGlmIChkZWJ1Zy51c2VfZGVmYXVsdCAmJiBvYmplY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKG9iamVjdCkgPyB0cnVlIDogZmFsc2U7XG4gICAgfVxufTtcblxuVHlwZXMudm9pZCA9IHtcbiAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCIodm9pZCkgdW5kZWZpbmVkIHR5cGVcIik7XG4gICAgfSxcbiAgICBhcHBlbmRCeXRlQnVmZmVyOiBmdW5jdGlvbiBhcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCIodm9pZCkgdW5kZWZpbmVkIHR5cGVcIik7XG4gICAgfSxcbiAgICBmcm9tT2JqZWN0OiBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCIodm9pZCkgdW5kZWZpbmVkIHR5cGVcIik7XG4gICAgfSxcbiAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgaWYgKGRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihcIih2b2lkKSB1bmRlZmluZWQgdHlwZVwiKTtcbiAgICB9XG59O1xuXG5UeXBlcy5hcnJheSA9IGZ1bmN0aW9uIChzdF9vcGVyYXRpb24pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICAgICAgdmFyIHNpemUgPSBiLnJlYWRWYXJpbnQzMigpO1xuICAgICAgICAgICAgaWYgKEhFWF9EVU1QKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJ2YXJpbnQzMiBzaXplID0gXCIgKyBzaXplLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgMCA8IHNpemUgPyBpIDwgc2l6ZSA6IGkgPiBzaXplOyAwIDwgc2l6ZSA/IGkrKyA6IGkrKykge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHN0X29wZXJhdGlvbi5mcm9tQnl0ZUJ1ZmZlcihiKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gc29ydE9wZXJhdGlvbihyZXN1bHQsIHN0X29wZXJhdGlvbik7XG4gICAgICAgIH0sXG4gICAgICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgICAgICB2LnJlcXVpcmVkKG9iamVjdCk7XG4gICAgICAgICAgICBvYmplY3QgPSBzb3J0T3BlcmF0aW9uKG9iamVjdCwgc3Rfb3BlcmF0aW9uKTtcbiAgICAgICAgICAgIGIud3JpdGVWYXJpbnQzMihvYmplY3QubGVuZ3RoKTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBvOyBpIDwgb2JqZWN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbyA9IG9iamVjdFtpXTtcbiAgICAgICAgICAgICAgICBzdF9vcGVyYXRpb24uYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICAgICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgICAgIG9iamVjdCA9IHNvcnRPcGVyYXRpb24ob2JqZWN0LCBzdF9vcGVyYXRpb24pO1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIG87IGkgPCBvYmplY3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBvID0gb2JqZWN0W2ldO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHN0X29wZXJhdGlvbi5mcm9tT2JqZWN0KG8pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH0sXG4gICAgICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgICAgIGlmIChkZWJ1Zy51c2VfZGVmYXVsdCAmJiBvYmplY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBbc3Rfb3BlcmF0aW9uLnRvT2JqZWN0KG9iamVjdCwgZGVidWcpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgICAgIG9iamVjdCA9IHNvcnRPcGVyYXRpb24ob2JqZWN0LCBzdF9vcGVyYXRpb24pO1xuXG4gICAgICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbzsgaSA8IG9iamVjdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIG8gPSBvYmplY3RbaV07XG4gICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goc3Rfb3BlcmF0aW9uLnRvT2JqZWN0KG8sIGRlYnVnKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICB9XG4gICAgfTtcbn07XG5cblR5cGVzLnRpbWVfcG9pbnRfc2VjID0ge1xuICAgIGZyb21CeXRlQnVmZmVyOiBmdW5jdGlvbiBmcm9tQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgIHJldHVybiBiLnJlYWRVaW50MzIoKTtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIGlmICh0eXBlb2Ygb2JqZWN0ICE9PSBcIm51bWJlclwiKSBvYmplY3QgPSBUeXBlcy50aW1lX3BvaW50X3NlYy5mcm9tT2JqZWN0KG9iamVjdCk7XG5cbiAgICAgICAgYi53cml0ZVVpbnQzMihvYmplY3QpO1xuICAgICAgICByZXR1cm47XG4gICAgfSxcbiAgICBmcm9tT2JqZWN0OiBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICB2LnJlcXVpcmVkKG9iamVjdCk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QgPT09IFwibnVtYmVyXCIpIHJldHVybiBvYmplY3Q7XG5cbiAgICAgICAgaWYgKG9iamVjdC5nZXRUaW1lKSByZXR1cm4gTWF0aC5mbG9vcihvYmplY3QuZ2V0VGltZSgpIC8gMTAwMCk7XG5cbiAgICAgICAgaWYgKHR5cGVvZiBvYmplY3QgIT09IFwic3RyaW5nXCIpIHRocm93IG5ldyBFcnJvcihcIlVua25vd24gZGF0ZSB0eXBlOiBcIiArIG9iamVjdCk7XG5cbiAgICAgICAgLy8gaWYodHlwZW9mIG9iamVjdCA9PT0gXCJzdHJpbmdcIiAmJiAhL1okLy50ZXN0KG9iamVjdCkpXG4gICAgICAgIC8vICAgICBvYmplY3QgPSBvYmplY3QgKyBcIlpcIlxuXG4gICAgICAgIHJldHVybiBNYXRoLmZsb29yKG5ldyBEYXRlKG9iamVjdCkuZ2V0VGltZSgpIC8gMTAwMCk7XG4gICAgfSxcbiAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgaWYgKGRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gbmV3IERhdGUoMCkudG9JU09TdHJpbmcoKS5zcGxpdCgnLicpWzBdO1xuXG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcblxuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gXCJzdHJpbmdcIikgcmV0dXJuIG9iamVjdDtcblxuICAgICAgICBpZiAob2JqZWN0LmdldFRpbWUpIHJldHVybiBvYmplY3QudG9JU09TdHJpbmcoKS5zcGxpdCgnLicpWzBdO1xuXG4gICAgICAgIHZhciBpbnQgPSBwYXJzZUludChvYmplY3QpO1xuICAgICAgICB2LnJlcXVpcmVfcmFuZ2UoMCwgMHhGRkZGRkZGRiwgaW50LCAndWludDMyICcgKyBvYmplY3QpO1xuICAgICAgICByZXR1cm4gbmV3IERhdGUoaW50ICogMTAwMCkudG9JU09TdHJpbmcoKS5zcGxpdCgnLicpWzBdO1xuICAgIH1cbn07XG5cblR5cGVzLnNldCA9IGZ1bmN0aW9uIChzdF9vcGVyYXRpb24pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB2YWxpZGF0ZTogZnVuY3Rpb24gdmFsaWRhdGUoYXJyYXkpIHtcbiAgICAgICAgICAgIHZhciBkdXBfbWFwID0ge307XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbzsgaSA8IGFycmF5Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbyA9IGFycmF5W2ldO1xuICAgICAgICAgICAgICAgIHZhciByZWY7XG4gICAgICAgICAgICAgICAgaWYgKHJlZiA9IHR5cGVvZiBvID09PSAndW5kZWZpbmVkJyA/ICd1bmRlZmluZWQnIDogX3R5cGVvZihvKSwgWydzdHJpbmcnLCAnbnVtYmVyJ10uaW5kZXhPZihyZWYpID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGR1cF9tYXBbb10gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZHVwbGljYXRlIChzZXQpXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGR1cF9tYXBbb10gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzb3J0T3BlcmF0aW9uKGFycmF5LCBzdF9vcGVyYXRpb24pO1xuICAgICAgICB9LFxuICAgICAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICAgICAgdmFyIHNpemUgPSBiLnJlYWRWYXJpbnQzMigpO1xuICAgICAgICAgICAgaWYgKEhFWF9EVU1QKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coXCJ2YXJpbnQzMiBzaXplID0gXCIgKyBzaXplLnRvU3RyaW5nKDE2KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyAwIDwgc2l6ZSA/IGkgPCBzaXplIDogaSA+IHNpemU7IDAgPCBzaXplID8gaSsrIDogaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHN0X29wZXJhdGlvbi5mcm9tQnl0ZUJ1ZmZlcihiKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9KCkpO1xuICAgICAgICB9LFxuICAgICAgICBhcHBlbmRCeXRlQnVmZmVyOiBmdW5jdGlvbiBhcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKCFvYmplY3QpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QgPSBbXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGIud3JpdGVWYXJpbnQzMihvYmplY3QubGVuZ3RoKTtcbiAgICAgICAgICAgIHZhciBpdGVyYWJsZSA9IHRoaXMudmFsaWRhdGUob2JqZWN0KTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBvOyBpIDwgaXRlcmFibGUubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBvID0gaXRlcmFibGVbaV07XG4gICAgICAgICAgICAgICAgc3Rfb3BlcmF0aW9uLmFwcGVuZEJ5dGVCdWZmZXIoYiwgbyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0sXG4gICAgICAgIGZyb21PYmplY3Q6IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAoIW9iamVjdCkge1xuICAgICAgICAgICAgICAgIG9iamVjdCA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbzsgaSA8IG9iamVjdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBvID0gb2JqZWN0W2ldO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChzdF9vcGVyYXRpb24uZnJvbU9iamVjdChvKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9KCkpO1xuICAgICAgICB9LFxuICAgICAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICAgICAgICBpZiAoZGVidWcudXNlX2RlZmF1bHQgJiYgb2JqZWN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW3N0X29wZXJhdGlvbi50b09iamVjdChvYmplY3QsIGRlYnVnKV07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIW9iamVjdCkge1xuICAgICAgICAgICAgICAgIG9iamVjdCA9IFtdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMudmFsaWRhdGUoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbzsgaSA8IG9iamVjdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBvID0gb2JqZWN0W2ldO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChzdF9vcGVyYXRpb24udG9PYmplY3QobywgZGVidWcpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0oKSk7XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuLy8gZ2xvYmFsX3BhcmFtZXRlcnNfdXBkYXRlX29wZXJhdGlvbiBjdXJyZW50X2ZlZXNcblR5cGVzLmZpeGVkX2FycmF5ID0gZnVuY3Rpb24gKGNvdW50LCBzdF9vcGVyYXRpb24pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICAgICAgdmFyIGksIGosIHJlZiwgcmVzdWx0cztcbiAgICAgICAgICAgIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoaSA9IGogPSAwLCByZWYgPSBjb3VudDsgaiA8IHJlZjsgaSA9IGogKz0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaChzdF9vcGVyYXRpb24uZnJvbUJ5dGVCdWZmZXIoYikpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHNvcnRPcGVyYXRpb24ocmVzdWx0cywgc3Rfb3BlcmF0aW9uKTtcbiAgICAgICAgfSxcbiAgICAgICAgYXBwZW5kQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3QpIHtcbiAgICAgICAgICAgIHZhciBpLCBqLCByZWY7XG4gICAgICAgICAgICBpZiAoY291bnQgIT09IDApIHtcbiAgICAgICAgICAgICAgICB2LnJlcXVpcmVkKG9iamVjdCk7XG4gICAgICAgICAgICAgICAgb2JqZWN0ID0gc29ydE9wZXJhdGlvbihvYmplY3QsIHN0X29wZXJhdGlvbik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKGkgPSBqID0gMCwgcmVmID0gY291bnQ7IGogPCByZWY7IGkgPSBqICs9IDEpIHtcbiAgICAgICAgICAgICAgICBzdF9vcGVyYXRpb24uYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3RbaV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9LFxuICAgICAgICBmcm9tT2JqZWN0OiBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgdmFyIGksIGosIHJlZiwgcmVzdWx0cztcbiAgICAgICAgICAgIGlmIChjb3VudCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdHMgPSBbXTtcbiAgICAgICAgICAgIGZvciAoaSA9IGogPSAwLCByZWYgPSBjb3VudDsgaiA8IHJlZjsgaSA9IGogKz0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaChzdF9vcGVyYXRpb24uZnJvbU9iamVjdChvYmplY3RbaV0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHRzO1xuICAgICAgICB9LFxuICAgICAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0LCBkZWJ1Zykge1xuICAgICAgICAgICAgdmFyIGksIGosIGssIHJlZiwgcmVmMSwgcmVzdWx0cywgcmVzdWx0czE7XG4gICAgICAgICAgICBpZiAoZGVidWcgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIGRlYnVnID0ge307XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZGVidWcudXNlX2RlZmF1bHQgJiYgb2JqZWN0ID09PSB2b2lkIDApIHtcbiAgICAgICAgICAgICAgICByZXN1bHRzID0gW107XG4gICAgICAgICAgICAgICAgZm9yIChpID0gaiA9IDAsIHJlZiA9IGNvdW50OyBqIDwgcmVmOyBpID0gaiArPSAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdHMucHVzaChzdF9vcGVyYXRpb24udG9PYmplY3Qodm9pZCAwLCBkZWJ1ZykpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0cztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjb3VudCAhPT0gMCkge1xuICAgICAgICAgICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJlc3VsdHMxID0gW107XG4gICAgICAgICAgICBmb3IgKGkgPSBrID0gMCwgcmVmMSA9IGNvdW50OyBrIDwgcmVmMTsgaSA9IGsgKz0gMSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdHMxLnB1c2goc3Rfb3BlcmF0aW9uLnRvT2JqZWN0KG9iamVjdFtpXSwgZGVidWcpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHRzMTtcbiAgICAgICAgfVxuICAgIH07XG59O1xuXG4vKiBTdXBwb3J0cyBpbnN0YW5jZSBudW1iZXJzICgxMSkgb3Igb2JqZWN0IHR5cGVzICgxLjIuMTEpLiAgT2JqZWN0IHR5cGVcblZhbGlkYXRpb24gaXMgZW5mb3JjZWQgd2hlbiBhbiBvYmplY3QgdHlwZSBpcyB1c2VkLiAqL1xudmFyIGlkX3R5cGUgPSBmdW5jdGlvbiBpZF90eXBlKHJlc2VydmVkX3NwYWNlcywgb2JqZWN0X3R5cGUpIHtcbiAgICB2LnJlcXVpcmVkKHJlc2VydmVkX3NwYWNlcywgXCJyZXNlcnZlZF9zcGFjZXNcIik7XG4gICAgdi5yZXF1aXJlZChvYmplY3RfdHlwZSwgXCJvYmplY3RfdHlwZVwiKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICAgICAgcmV0dXJuIGIucmVhZFZhcmludDMyKCk7XG4gICAgICAgIH0sXG4gICAgICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgICAgICB2LnJlcXVpcmVkKG9iamVjdCk7XG4gICAgICAgICAgICBpZiAob2JqZWN0LnJlc29sdmUgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIG9iamVjdCA9IG9iamVjdC5yZXNvbHZlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gY29udmVydCAxLjIubiBpbnRvIGp1c3QgblxuICAgICAgICAgICAgaWYgKC9eWzAtOV0rXFwuWzAtOV0rXFwuWzAtOV0rJC8udGVzdChvYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0ID0gdi5nZXRfaW5zdGFuY2UocmVzZXJ2ZWRfc3BhY2VzLCBvYmplY3RfdHlwZSwgb2JqZWN0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGIud3JpdGVWYXJpbnQzMih2LnRvX251bWJlcihvYmplY3QpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSxcbiAgICAgICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgICAgIGlmIChvYmplY3QucmVzb2x2ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0ID0gb2JqZWN0LnJlc29sdmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodi5pc19kaWdpdHMob2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB2LnRvX251bWJlcihvYmplY3QpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHYuZ2V0X2luc3RhbmNlKHJlc2VydmVkX3NwYWNlcywgb2JqZWN0X3R5cGUsIG9iamVjdCk7XG4gICAgICAgIH0sXG4gICAgICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgICAgIHZhciBvYmplY3RfdHlwZV9pZCA9IENoYWluVHlwZXMub2JqZWN0X3R5cGVbb2JqZWN0X3R5cGVdO1xuICAgICAgICAgICAgaWYgKGRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc2VydmVkX3NwYWNlcyArICcuJyArIG9iamVjdF90eXBlX2lkICsgJy4wJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgICAgIGlmIChvYmplY3QucmVzb2x2ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgb2JqZWN0ID0gb2JqZWN0LnJlc29sdmU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoL15bMC05XStcXC5bMC05XStcXC5bMC05XSskLy50ZXN0KG9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICBvYmplY3QgPSB2LmdldF9pbnN0YW5jZShyZXNlcnZlZF9zcGFjZXMsIG9iamVjdF90eXBlLCBvYmplY3QpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gcmVzZXJ2ZWRfc3BhY2VzICsgJy4nICsgb2JqZWN0X3R5cGVfaWQgKyAnLicgKyBvYmplY3Q7XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuVHlwZXMucHJvdG9jb2xfaWRfdHlwZSA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdi5yZXF1aXJlZChuYW1lLCBcIm5hbWVcIik7XG4gICAgcmV0dXJuIGlkX3R5cGUoQ2hhaW5UeXBlcy5yZXNlcnZlZF9zcGFjZXMucHJvdG9jb2xfaWRzLCBuYW1lKTtcbn07XG5cblR5cGVzLm9iamVjdF9pZF90eXBlID0ge1xuICAgIGZyb21CeXRlQnVmZmVyOiBmdW5jdGlvbiBmcm9tQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgIHJldHVybiBPYmplY3RJZC5mcm9tQnl0ZUJ1ZmZlcihiKTtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgaWYgKG9iamVjdC5yZXNvbHZlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIG9iamVjdCA9IG9iamVjdC5yZXNvbHZlO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdCA9IE9iamVjdElkLmZyb21TdHJpbmcob2JqZWN0KTtcbiAgICAgICAgb2JqZWN0LmFwcGVuZEJ5dGVCdWZmZXIoYik7XG4gICAgICAgIHJldHVybjtcbiAgICB9LFxuICAgIGZyb21PYmplY3Q6IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgaWYgKG9iamVjdC5yZXNvbHZlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIG9iamVjdCA9IG9iamVjdC5yZXNvbHZlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBPYmplY3RJZC5mcm9tU3RyaW5nKG9iamVjdCk7XG4gICAgfSxcbiAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgaWYgKGRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gXCIwLjAuMFwiO1xuICAgICAgICB9XG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgaWYgKG9iamVjdC5yZXNvbHZlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIG9iamVjdCA9IG9iamVjdC5yZXNvbHZlO1xuICAgICAgICB9XG4gICAgICAgIG9iamVjdCA9IE9iamVjdElkLmZyb21TdHJpbmcob2JqZWN0KTtcbiAgICAgICAgcmV0dXJuIG9iamVjdC50b1N0cmluZygpO1xuICAgIH1cbn07XG5cblR5cGVzLnZvdGVfaWQgPSB7IFRZUEU6IDB4MDAwMDAwRkYsXG4gICAgSUQ6IDB4RkZGRkZGMDAsXG4gICAgZnJvbUJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgdmFyIHZhbHVlID0gYi5yZWFkVWludDMyKCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0eXBlOiB2YWx1ZSAmIHRoaXMuVFlQRSxcbiAgICAgICAgICAgIGlkOiB2YWx1ZSAmIHRoaXMuSURcbiAgICAgICAgfTtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgaWYgKG9iamVjdCA9PT0gXCJzdHJpbmdcIikgb2JqZWN0ID0gVHlwZXMudm90ZV9pZC5mcm9tT2JqZWN0KG9iamVjdCk7XG5cbiAgICAgICAgdmFyIHZhbHVlID0gb2JqZWN0LmlkIDw8IDggfCBvYmplY3QudHlwZTtcbiAgICAgICAgYi53cml0ZVVpbnQzMih2YWx1ZSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9LFxuICAgIGZyb21PYmplY3Q6IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHYucmVxdWlyZWQob2JqZWN0LCBcIih0eXBlIHZvdGVfaWQpXCIpO1xuICAgICAgICBpZiAoKHR5cGVvZiBvYmplY3QgPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKG9iamVjdCkpID09PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICB2LnJlcXVpcmVkKG9iamVjdC50eXBlLCBcInR5cGVcIik7XG4gICAgICAgICAgICB2LnJlcXVpcmVkKG9iamVjdC5pZCwgXCJpZFwiKTtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH1cbiAgICAgICAgdi5yZXF1aXJlX3Rlc3QoL15bMC05XSs6WzAtOV0rJC8sIG9iamVjdCwgJ3ZvdGVfaWQgZm9ybWF0ICcgKyBvYmplY3QpO1xuXG4gICAgICAgIHZhciBfb2JqZWN0JHNwbGl0ID0gb2JqZWN0LnNwbGl0KCc6JyksXG4gICAgICAgICAgICBfb2JqZWN0JHNwbGl0MiA9IF9zbGljZWRUb0FycmF5KF9vYmplY3Qkc3BsaXQsIDIpLFxuICAgICAgICAgICAgdHlwZSA9IF9vYmplY3Qkc3BsaXQyWzBdLFxuICAgICAgICAgICAgaWQgPSBfb2JqZWN0JHNwbGl0MlsxXTtcblxuICAgICAgICB2LnJlcXVpcmVfcmFuZ2UoMCwgMHhmZiwgdHlwZSwgJ3ZvdGUgdHlwZSAnICsgb2JqZWN0KTtcbiAgICAgICAgdi5yZXF1aXJlX3JhbmdlKDAsIDB4ZmZmZmZmLCBpZCwgJ3ZvdGUgaWQgJyArIG9iamVjdCk7XG4gICAgICAgIHJldHVybiB7IHR5cGU6IHR5cGUsIGlkOiBpZCB9O1xuICAgIH0sXG4gICAgdG9PYmplY3Q6IGZ1bmN0aW9uIHRvT2JqZWN0KG9iamVjdCkge1xuICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICAgIGlmIChkZWJ1Zy51c2VfZGVmYXVsdCAmJiBvYmplY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuIFwiMDowXCI7XG4gICAgICAgIH1cbiAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCA9PT0gXCJzdHJpbmdcIikgb2JqZWN0ID0gVHlwZXMudm90ZV9pZC5mcm9tT2JqZWN0KG9iamVjdCk7XG5cbiAgICAgICAgcmV0dXJuIG9iamVjdC50eXBlICsgXCI6XCIgKyBvYmplY3QuaWQ7XG4gICAgfSxcbiAgICBjb21wYXJlOiBmdW5jdGlvbiBjb21wYXJlKGEsIGIpIHtcbiAgICAgICAgaWYgKCh0eXBlb2YgYSA9PT0gJ3VuZGVmaW5lZCcgPyAndW5kZWZpbmVkJyA6IF90eXBlb2YoYSkpICE9PSBcIm9iamVjdFwiKSBhID0gVHlwZXMudm90ZV9pZC5mcm9tT2JqZWN0KGEpO1xuICAgICAgICBpZiAoKHR5cGVvZiBiID09PSAndW5kZWZpbmVkJyA/ICd1bmRlZmluZWQnIDogX3R5cGVvZihiKSkgIT09IFwib2JqZWN0XCIpIGIgPSBUeXBlcy52b3RlX2lkLmZyb21PYmplY3QoYik7XG4gICAgICAgIHJldHVybiBwYXJzZUludChhLmlkKSAtIHBhcnNlSW50KGIuaWQpO1xuICAgIH1cbn07XG5cblR5cGVzLm9wdGlvbmFsID0gZnVuY3Rpb24gKHN0X29wZXJhdGlvbikge1xuICAgIHYucmVxdWlyZWQoc3Rfb3BlcmF0aW9uLCBcInN0X29wZXJhdGlvblwiKTtcbiAgICByZXR1cm4ge1xuICAgICAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICAgICAgaWYgKCEoYi5yZWFkVWludDgoKSA9PT0gMSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdW5kZWZpbmVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHN0X29wZXJhdGlvbi5mcm9tQnl0ZUJ1ZmZlcihiKTtcbiAgICAgICAgfSxcbiAgICAgICAgYXBwZW5kQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QgIT09IG51bGwgJiYgb2JqZWN0ICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBiLndyaXRlVWludDgoMSk7XG4gICAgICAgICAgICAgICAgc3Rfb3BlcmF0aW9uLmFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgYi53cml0ZVVpbnQ4KDApO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9LFxuICAgICAgICBmcm9tT2JqZWN0OiBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHVuZGVmaW5lZDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzdF9vcGVyYXRpb24uZnJvbU9iamVjdChvYmplY3QpO1xuICAgICAgICB9LFxuICAgICAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICAgICAgICAvLyB0b09iamVjdCBpcyBvbmx5IG51bGwgc2F2ZSBpZiB1c2VfZGVmYXVsdCBpcyB0cnVlXG4gICAgICAgICAgICB2YXIgcmVzdWx0X29iamVjdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBpZiAoIWRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB1bmRlZmluZWQ7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHN0X29wZXJhdGlvbi50b09iamVjdChvYmplY3QsIGRlYnVnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KCk7XG5cbiAgICAgICAgICAgIGlmIChkZWJ1Zy5hbm5vdGF0ZSkge1xuICAgICAgICAgICAgICAgIGlmICgodHlwZW9mIHJlc3VsdF9vYmplY3QgPT09ICd1bmRlZmluZWQnID8gJ3VuZGVmaW5lZCcgOiBfdHlwZW9mKHJlc3VsdF9vYmplY3QpKSA9PT0gXCJvYmplY3RcIikge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHRfb2JqZWN0Ll9fb3B0aW9uYWwgPSBcInBhcmVudCBpcyBvcHRpb25hbFwiO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdF9vYmplY3QgPSB7IF9fb3B0aW9uYWw6IHJlc3VsdF9vYmplY3QgfTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gcmVzdWx0X29iamVjdDtcbiAgICAgICAgfVxuICAgIH07XG59O1xuXG5UeXBlcy5zdGF0aWNfdmFyaWFudCA9IGZ1bmN0aW9uIChfc3Rfb3BlcmF0aW9ucykge1xuICAgIHJldHVybiB7XG4gICAgICAgIG5vc29ydDogdHJ1ZSxcbiAgICAgICAgc3Rfb3BlcmF0aW9uczogX3N0X29wZXJhdGlvbnMsXG4gICAgICAgIGZyb21CeXRlQnVmZmVyOiBmdW5jdGlvbiBmcm9tQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgICAgICB2YXIgdHlwZV9pZCA9IGIucmVhZFZhcmludDMyKCk7XG4gICAgICAgICAgICB2YXIgc3Rfb3BlcmF0aW9uID0gdGhpcy5zdF9vcGVyYXRpb25zW3R5cGVfaWRdO1xuICAgICAgICAgICAgaWYgKEhFWF9EVU1QKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5lcnJvcignc3RhdGljX3ZhcmlhbnQgaWQgMHgnICsgdHlwZV9pZC50b1N0cmluZygxNikgKyAnICgnICsgdHlwZV9pZCArICcpJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2LnJlcXVpcmVkKHN0X29wZXJhdGlvbiwgJ29wZXJhdGlvbiAnICsgdHlwZV9pZCk7XG4gICAgICAgICAgICByZXR1cm4gW3R5cGVfaWQsIHN0X29wZXJhdGlvbi5mcm9tQnl0ZUJ1ZmZlcihiKV07XG4gICAgICAgIH0sXG4gICAgICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgICAgICB2LnJlcXVpcmVkKG9iamVjdCk7XG4gICAgICAgICAgICB2YXIgdHlwZV9pZCA9IG9iamVjdFswXTtcbiAgICAgICAgICAgIHZhciBzdF9vcGVyYXRpb24gPSB0aGlzLnN0X29wZXJhdGlvbnNbdHlwZV9pZF07XG4gICAgICAgICAgICB2LnJlcXVpcmVkKHN0X29wZXJhdGlvbiwgJ29wZXJhdGlvbiAnICsgdHlwZV9pZCk7XG4gICAgICAgICAgICBiLndyaXRlVmFyaW50MzIodHlwZV9pZCk7XG4gICAgICAgICAgICBzdF9vcGVyYXRpb24uYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3RbMV0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9LFxuICAgICAgICBmcm9tT2JqZWN0OiBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICAgICAgdmFyIHR5cGVfaWQgPSBvYmplY3RbMF07XG4gICAgICAgICAgICB2YXIgc3Rfb3BlcmF0aW9uID0gdGhpcy5zdF9vcGVyYXRpb25zW3R5cGVfaWRdO1xuICAgICAgICAgICAgdi5yZXF1aXJlZChzdF9vcGVyYXRpb24sICdvcGVyYXRpb24gJyArIHR5cGVfaWQpO1xuICAgICAgICAgICAgcmV0dXJuIFt0eXBlX2lkLCBzdF9vcGVyYXRpb24uZnJvbU9iamVjdChvYmplY3RbMV0pXTtcbiAgICAgICAgfSxcbiAgICAgICAgdG9PYmplY3Q6IGZ1bmN0aW9uIHRvT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgdmFyIGRlYnVnID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcblxuICAgICAgICAgICAgaWYgKGRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFswLCB0aGlzLnN0X29wZXJhdGlvbnNbMF0udG9PYmplY3QodW5kZWZpbmVkLCBkZWJ1ZyldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICAgICAgdmFyIHR5cGVfaWQgPSBvYmplY3RbMF07XG4gICAgICAgICAgICB2YXIgc3Rfb3BlcmF0aW9uID0gdGhpcy5zdF9vcGVyYXRpb25zW3R5cGVfaWRdO1xuICAgICAgICAgICAgdi5yZXF1aXJlZChzdF9vcGVyYXRpb24sICdvcGVyYXRpb24gJyArIHR5cGVfaWQpO1xuICAgICAgICAgICAgcmV0dXJuIFt0eXBlX2lkLCBzdF9vcGVyYXRpb24udG9PYmplY3Qob2JqZWN0WzFdLCBkZWJ1ZyldO1xuICAgICAgICB9XG4gICAgfTtcbn07XG5cblR5cGVzLm1hcCA9IGZ1bmN0aW9uIChrZXlfc3Rfb3BlcmF0aW9uLCB2YWx1ZV9zdF9vcGVyYXRpb24pIHtcbiAgICByZXR1cm4ge1xuICAgICAgICB2YWxpZGF0ZTogZnVuY3Rpb24gdmFsaWRhdGUoYXJyYXkpIHtcbiAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShhcnJheSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJleHBlY3RpbmcgYXJyYXlcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgZHVwX21hcCA9IHt9O1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIG87IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIG8gPSBhcnJheVtpXTtcbiAgICAgICAgICAgICAgICB2YXIgcmVmO1xuICAgICAgICAgICAgICAgIGlmICghKG8ubGVuZ3RoID09PSAyKSkge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJleHBlY3RpbmcgdHdvIGVsZW1lbnRzXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmVmID0gX3R5cGVvZihvWzBdKSwgWydudW1iZXInLCAnc3RyaW5nJ10uaW5kZXhPZihyZWYpID49IDApIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGR1cF9tYXBbb1swXV0gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZHVwbGljYXRlIChtYXApXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGR1cF9tYXBbb1swXV0gPSB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBzb3J0T3BlcmF0aW9uKGFycmF5LCBrZXlfc3Rfb3BlcmF0aW9uKTtcbiAgICAgICAgfSxcbiAgICAgICAgZnJvbUJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgIHZhciBlbmQgPSBiLnJlYWRWYXJpbnQzMigpO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IDAgPCBlbmQgPyBpIDwgZW5kIDogaSA+IGVuZDsgMCA8IGVuZCA/IGkrKyA6IGkrKykge1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFtrZXlfc3Rfb3BlcmF0aW9uLmZyb21CeXRlQnVmZmVyKGIpLCB2YWx1ZV9zdF9vcGVyYXRpb24uZnJvbUJ5dGVCdWZmZXIoYildKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnZhbGlkYXRlKHJlc3VsdCk7XG4gICAgICAgIH0sXG4gICAgICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgICAgICB0aGlzLnZhbGlkYXRlKG9iamVjdCk7XG4gICAgICAgICAgICBiLndyaXRlVmFyaW50MzIob2JqZWN0Lmxlbmd0aCk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMCwgbzsgaSA8IG9iamVjdC5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgICAgIG8gPSBvYmplY3RbaV07XG4gICAgICAgICAgICAgICAga2V5X3N0X29wZXJhdGlvbi5hcHBlbmRCeXRlQnVmZmVyKGIsIG9bMF0pO1xuICAgICAgICAgICAgICAgIHZhbHVlX3N0X29wZXJhdGlvbi5hcHBlbmRCeXRlQnVmZmVyKGIsIG9bMV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9LFxuICAgICAgICBmcm9tT2JqZWN0OiBmdW5jdGlvbiBmcm9tT2JqZWN0KG9iamVjdCkge1xuICAgICAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICAgICAgdmFyIHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIG87IGkgPCBvYmplY3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBvID0gb2JqZWN0W2ldO1xuICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKFtrZXlfc3Rfb3BlcmF0aW9uLmZyb21PYmplY3Qob1swXSksIHZhbHVlX3N0X29wZXJhdGlvbi5mcm9tT2JqZWN0KG9bMV0pXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gdGhpcy52YWxpZGF0ZShyZXN1bHQpO1xuICAgICAgICB9LFxuICAgICAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICAgICAgICBpZiAoZGVidWcudXNlX2RlZmF1bHQgJiYgb2JqZWN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gW1trZXlfc3Rfb3BlcmF0aW9uLnRvT2JqZWN0KHVuZGVmaW5lZCwgZGVidWcpLCB2YWx1ZV9zdF9vcGVyYXRpb24udG9PYmplY3QodW5kZWZpbmVkLCBkZWJ1ZyldXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHYucmVxdWlyZWQob2JqZWN0KTtcbiAgICAgICAgICAgIG9iamVjdCA9IHRoaXMudmFsaWRhdGUob2JqZWN0KTtcbiAgICAgICAgICAgIHZhciByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwLCBvOyBpIDwgb2JqZWN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgbyA9IG9iamVjdFtpXTtcbiAgICAgICAgICAgICAgICByZXN1bHQucHVzaChba2V5X3N0X29wZXJhdGlvbi50b09iamVjdChvWzBdLCBkZWJ1ZyksIHZhbHVlX3N0X29wZXJhdGlvbi50b09iamVjdChvWzFdLCBkZWJ1ZyldKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuVHlwZXMucHVibGljX2tleSA9IHtcbiAgICB0b1B1YmxpYzogZnVuY3Rpb24gdG9QdWJsaWMob2JqZWN0KSB7XG4gICAgICAgIGlmIChvYmplY3QucmVzb2x2ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBvYmplY3QgPSBvYmplY3QucmVzb2x2ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvYmplY3QgaW5zdGFuY2VvZiBQdWJsaWNLZXkpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb2JqZWN0ID09IG51bGwgPyBvYmplY3QgOiBvYmplY3QuUSA/IG9iamVjdCA6IFB1YmxpY0tleS5mcm9tU3RyaW5nT3JUaHJvdyhvYmplY3QpO1xuICAgIH0sXG4gICAgZnJvbUJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgcmV0dXJuIGZwLnB1YmxpY19rZXkoYik7XG4gICAgfSxcbiAgICBhcHBlbmRCeXRlQnVmZmVyOiBmdW5jdGlvbiBhcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCkge1xuICAgICAgICB2LnJlcXVpcmVkKG9iamVjdCk7XG4gICAgICAgIGZwLnB1YmxpY19rZXkoYiwgVHlwZXMucHVibGljX2tleS50b1B1YmxpYyhvYmplY3QpKTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH0sXG4gICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgdi5yZXF1aXJlZChvYmplY3QpO1xuICAgICAgICBpZiAob2JqZWN0LlEpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFR5cGVzLnB1YmxpY19rZXkudG9QdWJsaWMob2JqZWN0KTtcbiAgICB9LFxuICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgdmFyIGRlYnVnID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcblxuICAgICAgICBpZiAoZGVidWcudXNlX2RlZmF1bHQgJiYgb2JqZWN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBDaGFpbkNvbmZpZy5hZGRyZXNzX3ByZWZpeCArIFwiODU5Z3hmblh5VXJpTWdVZVRoaDFmV3Yzb3FjcExGeUhhM1RmRllDNFBLMkhxaFRvVk1cIjtcbiAgICAgICAgfVxuICAgICAgICB2LnJlcXVpcmVkKG9iamVjdCk7XG4gICAgICAgIHJldHVybiBvYmplY3QudG9TdHJpbmcoKTtcbiAgICB9LFxuICAgIGNvbXBhcmU6IGZ1bmN0aW9uIGNvbXBhcmUoYSwgYikge1xuICAgICAgICByZXR1cm4gc3RyQ21wKGEudG9BZGRyZXNzU3RyaW5nKCksIGIudG9BZGRyZXNzU3RyaW5nKCkpO1xuICAgIH1cbn07XG5cblR5cGVzLmFkZHJlc3MgPSB7XG4gICAgX3RvX2FkZHJlc3M6IGZ1bmN0aW9uIF90b19hZGRyZXNzKG9iamVjdCkge1xuICAgICAgICB2LnJlcXVpcmVkKG9iamVjdCk7XG4gICAgICAgIGlmIChvYmplY3QuYWRkeSkge1xuICAgICAgICAgICAgcmV0dXJuIG9iamVjdDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQWRkcmVzcy5mcm9tU3RyaW5nKG9iamVjdCk7XG4gICAgfSxcbiAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICByZXR1cm4gbmV3IEFkZHJlc3MoZnAucmlwZW1kMTYwKGIpKTtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIGZwLnJpcGVtZDE2MChiLCBUeXBlcy5hZGRyZXNzLl90b19hZGRyZXNzKG9iamVjdCkudG9CdWZmZXIoKSk7XG4gICAgICAgIHJldHVybjtcbiAgICB9LFxuICAgIGZyb21PYmplY3Q6IGZ1bmN0aW9uIGZyb21PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHJldHVybiBUeXBlcy5hZGRyZXNzLl90b19hZGRyZXNzKG9iamVjdCk7XG4gICAgfSxcbiAgICB0b09iamVjdDogZnVuY3Rpb24gdG9PYmplY3Qob2JqZWN0KSB7XG4gICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgaWYgKGRlYnVnLnVzZV9kZWZhdWx0ICYmIG9iamVjdCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICByZXR1cm4gQ2hhaW5Db25maWcuYWRkcmVzc19wcmVmaXggKyBcIjY2NEttSHhTdVF5RHNmd280V0VKdldwemcxUUtkZzY3U1wiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBUeXBlcy5hZGRyZXNzLl90b19hZGRyZXNzKG9iamVjdCkudG9TdHJpbmcoKTtcbiAgICB9LFxuICAgIGNvbXBhcmU6IGZ1bmN0aW9uIGNvbXBhcmUoYSwgYikge1xuICAgICAgICByZXR1cm4gc3RyQ21wKGEudG9TdHJpbmcoKSwgYi50b1N0cmluZygpKTtcbiAgICB9XG59O1xuXG5UeXBlcy52YXJpYW50ID0ge1xuICAgIGZyb21CeXRlQnVmZmVyOiBmdW5jdGlvbiBmcm9tQnl0ZUJ1ZmZlcihiKSB7XG4gICAgICAgIHZhciB0eXBlID0gYi5yZWFkVWludDgoKTtcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFR5cGVzLmludDY0LmZyb21CeXRlQnVmZmVyKGIpO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIHJldHVybiBUeXBlcy51aW50NjQuZnJvbUJ5dGVCdWZmZXIoYik7XG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGIucmVhZERvdWJsZSgpO1xuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIHJldHVybiBUeXBlcy5ib29sLmZyb21CeXRlQnVmZmVyKGIpO1xuICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgIHJldHVybiBUeXBlcy5zdHJpbmcuZnJvbUJ5dGVCdWZmZXIoYik7XG4gICAgICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgICAgICAgcmV0dXJuIFR5cGVzLmFycmF5KFR5cGVzLnZhcmlhbnQpLmZyb21CeXRlQnVmZmVyKGIpO1xuICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gVHlwZXMudmFyaWFudF9vYmplY3QuZnJvbUJ5dGVCdWZmZXIoYik7XG4gICAgICAgIH07XG4gICAgfSxcbiAgICBhcHBlbmRCeXRlQnVmZmVyOiBmdW5jdGlvbiBhcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCkge1xuICAgICAgICBpZiAodHlwZW9mIG9iamVjdCA9PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgaWYgKE51bWJlci5pc0ludGVnZXIob2JqZWN0KSkge1xuICAgICAgICAgICAgICAgIGlmIChvYmplY3QgPj0gMCkge1xuICAgICAgICAgICAgICAgICAgICBiLndyaXRlVWludDgoMik7XG4gICAgICAgICAgICAgICAgICAgIFR5cGVzLnVpbnQ2NC5hcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYi53cml0ZVVpbnQ4KDEpO1xuICAgICAgICAgICAgICAgICAgICBUeXBlcy5pbnQ2NC5hcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBiLndyaXRlVWludDgoMyk7XG4gICAgICAgICAgICAgICAgYi53cml0ZURvdWJsZShOdW1iZXIucGFyc2VGbG9hdChvYmplY3QpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0ID09ICdib29sZWFuJykge1xuICAgICAgICAgICAgYi53cml0ZVVpbnQ4KDQpO1xuICAgICAgICAgICAgVHlwZXMuYm9vbC5hcHBlbmRCeXRlQnVmZmVyKGIsIG9iamVjdCk7XG4gICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIG9iamVjdCA9PSAnc3RyaW5nJykge1xuICAgICAgICAgICAgYi53cml0ZVVpbnQ4KDUpO1xuICAgICAgICAgICAgVHlwZXMuc3RyaW5nLmFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KTtcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2Ygb2JqZWN0ID09ICdhcnJheScpIHtcbiAgICAgICAgICAgIGIud3JpdGVVaW50OCg2KTtcbiAgICAgICAgICAgIFR5cGVzLmFycmF5KFR5cGVzLnZhcmlhbnQpLmFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGIud3JpdGVVaW50OCg3KTtcbiAgICAgICAgICAgIFR5cGVzLnZhcmlhbnRfb2JqZWN0LmFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KTtcbiAgICAgICAgfVxuICAgIH0sXG4gICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgcmV0dXJuIEpTT04ucGFyc2Uob2JqZWN0KTtcbiAgICB9LFxuICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgdmFyIGRlYnVnID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB7fTtcblxuICAgICAgICBpZiAoZGVidWcudXNlX2RlZmF1bHQgJiYgb2JqZWN0ID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBKU09OLnBhcnNlKG9iamVjdCk7XG4gICAgfVxufTtcblxuVHlwZXMudmFyaWFudF9vYmplY3QgPSB7XG4gICAgZnJvbUJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGZyb21CeXRlQnVmZmVyKGIpIHtcbiAgICAgICAgdmFyIGNvdW50ID0gYi5yZWFkVmFyaW50MzIoKTtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHt9O1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyArK2kpIHtcbiAgICAgICAgICAgIHZhciBrZXkgPSBUeXBlcy5zdHJpbmcuZnJvbUJ5dGVCdWZmZXIoYik7XG4gICAgICAgICAgICByZXN1bHRba2V5XSA9IFR5cGVzLnZhcmlhbnQuZnJvbUJ5dGVCdWZmZXIoYik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9LFxuICAgIGFwcGVuZEJ5dGVCdWZmZXI6IGZ1bmN0aW9uIGFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0KSB7XG4gICAgICAgIHZhciBjb3VudCA9IDA7XG4gICAgICAgIGZvciAodmFyIGtleSBpbiBvYmplY3QpIHtcbiAgICAgICAgICAgIGlmIChvYmplY3QuaGFzT3duUHJvcGVydHkoa2V5KSkgKytjb3VudDtcbiAgICAgICAgfWIud3JpdGVWYXJpbnQzMihjb3VudCk7IC8vIG51bWJlciBvZiBrZXkvdmFsdWUgcGFpcnNcbiAgICAgICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdC5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgVHlwZXMuc3RyaW5nLmFwcGVuZEJ5dGVCdWZmZXIoYiwga2V5KTtcbiAgICAgICAgICAgICAgICBUeXBlcy52YXJpYW50LmFwcGVuZEJ5dGVCdWZmZXIoYiwgb2JqZWN0W2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9cmV0dXJuO1xuICAgIH0sXG4gICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgdmFyIG5ld09iamVjdCA9IHt9O1xuICAgICAgICBmb3IgKHZhciBrZXkgaW4gb2JqZWN0KSB7XG4gICAgICAgICAgICBpZiAob2JqZWN0Lmhhc093blByb3BlcnR5KGtleSkpIG5ld09iamVjdFtrZXldID0gb2JqZWN0W2tleV07XG4gICAgICAgIH1yZXR1cm4gbmV3T2JqZWN0O1xuICAgIH0sXG4gICAgdG9PYmplY3Q6IGZ1bmN0aW9uIHRvT2JqZWN0KG9iamVjdCkge1xuICAgICAgICB2YXIgZGVidWcgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICAgIHZhciBuZXdPYmplY3QgPSB7fTtcbiAgICAgICAgZm9yICh2YXIga2V5IGluIG9iamVjdCkge1xuICAgICAgICAgICAgaWYgKG9iamVjdC5oYXNPd25Qcm9wZXJ0eShrZXkpKSBuZXdPYmplY3Rba2V5XSA9IG9iamVjdFtrZXldO1xuICAgICAgICB9cmV0dXJuIG5ld09iamVjdDtcbiAgICB9XG59O1xuXG5UeXBlcy5lbnVtZXJhdGlvbiA9IGZ1bmN0aW9uICh2YWx1ZXMpIHtcbiAgICByZXR1cm4ge1xuICAgICAgICBmcm9tQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gZnJvbUJ5dGVCdWZmZXIoYikge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlc1tiLnJlYWRWYXJpbnQzMlppZ1phZygpXTtcbiAgICAgICAgfSxcbiAgICAgICAgYXBwZW5kQnl0ZUJ1ZmZlcjogZnVuY3Rpb24gYXBwZW5kQnl0ZUJ1ZmZlcihiLCBvYmplY3QpIHtcbiAgICAgICAgICAgIGIud3JpdGVWYXJpbnQzMlppZ1phZyh2YWx1ZXMuaW5kZXhPZihvYmplY3QpKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSxcbiAgICAgICAgZnJvbU9iamVjdDogZnVuY3Rpb24gZnJvbU9iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH0sXG4gICAgICAgIHRvT2JqZWN0OiBmdW5jdGlvbiB0b09iamVjdChvYmplY3QpIHtcbiAgICAgICAgICAgIHZhciBkZWJ1ZyA9IGFyZ3VtZW50cy5sZW5ndGggPiAxICYmIGFyZ3VtZW50c1sxXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzFdIDoge307XG5cbiAgICAgICAgICAgIGlmIChkZWJ1Zy51c2VfZGVmYXVsdCAmJiBvYmplY3QgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIHZhbHVlc1swXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBvYmplY3Q7XG4gICAgICAgIH1cbiAgICB9O1xufTtcblxuVHlwZXMuc2hhMjU2ID0gVHlwZXMuYnl0ZXMoMzIpO1xuXG52YXIgc3RyQ21wID0gZnVuY3Rpb24gc3RyQ21wKGEsIGIpIHtcbiAgICByZXR1cm4gYSA+IGIgPyAxIDogYSA8IGIgPyAtMSA6IDA7XG59O1xudmFyIGZpcnN0RWwgPSBmdW5jdGlvbiBmaXJzdEVsKGVsKSB7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoZWwpID8gZWxbMF0gOiBlbDtcbn07XG52YXIgc29ydE9wZXJhdGlvbiA9IGZ1bmN0aW9uIHNvcnRPcGVyYXRpb24oYXJyYXksIHN0X29wZXJhdGlvbikge1xuICAgIHJldHVybiBzdF9vcGVyYXRpb24ubm9zb3J0ID8gYXJyYXkgOiBzdF9vcGVyYXRpb24uY29tcGFyZSA/IGFycmF5LnNvcnQoZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgICAgcmV0dXJuIHN0X29wZXJhdGlvbi5jb21wYXJlKGZpcnN0RWwoYSksIGZpcnN0RWwoYikpO1xuICAgIH0pIDogLy8gY3VzdG9tIGNvbXBhcmUgb3BlcmF0aW9uXG4gICAgYXJyYXkuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIGZpcnN0RWwoYSkgPT09IFwibnVtYmVyXCIgJiYgdHlwZW9mIGZpcnN0RWwoYikgPT09IFwibnVtYmVyXCIgPyBmaXJzdEVsKGEpIC0gZmlyc3RFbChiKSA6XG4gICAgICAgIC8vIEEgYmluYXJ5IHN0cmluZyBjb21wYXJlIGRvZXMgbm90IHdvcmsuIFBlcmZvcm1hbmFuY2UgaXMgdmVyeSBnb29kIHNvIEhFWCBpcyB1c2VkLi4gIGxvY2FsZUNvbXBhcmUgaXMgYW5vdGhlciBvcHRpb24uXG4gICAgICAgIEJ1ZmZlci5pc0J1ZmZlcihmaXJzdEVsKGEpKSAmJiBCdWZmZXIuaXNCdWZmZXIoZmlyc3RFbChiKSkgPyBzdHJDbXAoZmlyc3RFbChhKS50b1N0cmluZyhcImhleFwiKSwgZmlyc3RFbChiKS50b1N0cmluZyhcImhleFwiKSkgOiBzdHJDbXAoZmlyc3RFbChhKS50b1N0cmluZygpLCBmaXJzdEVsKGIpLnRvU3RyaW5nKCkpO1xuICAgIH0pO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbi8vIGNvbXBhcmUgYW5kIGlzQnVmZmVyIHRha2VuIGZyb20gaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvYmxvYi82ODBlOWU1ZTQ4OGYyMmFhYzI3NTk5YTU3ZGM4NDRhNjMxNTkyOGRkL2luZGV4LmpzXG4vLyBvcmlnaW5hbCBub3RpY2U6XG5cbi8qIVxuICogVGhlIGJ1ZmZlciBtb2R1bGUgZnJvbSBub2RlLmpzLCBmb3IgdGhlIGJyb3dzZXIuXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGZlcm9zc0BmZXJvc3Mub3JnPiA8aHR0cDovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cbmZ1bmN0aW9uIGNvbXBhcmUoYSwgYikge1xuICBpZiAoYSA9PT0gYikge1xuICAgIHJldHVybiAwO1xuICB9XG5cbiAgdmFyIHggPSBhLmxlbmd0aDtcbiAgdmFyIHkgPSBiLmxlbmd0aDtcblxuICBmb3IgKHZhciBpID0gMCwgbGVuID0gTWF0aC5taW4oeCwgeSk7IGkgPCBsZW47ICsraSkge1xuICAgIGlmIChhW2ldICE9PSBiW2ldKSB7XG4gICAgICB4ID0gYVtpXTtcbiAgICAgIHkgPSBiW2ldO1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgaWYgKHggPCB5KSB7XG4gICAgcmV0dXJuIC0xO1xuICB9XG4gIGlmICh5IDwgeCkge1xuICAgIHJldHVybiAxO1xuICB9XG4gIHJldHVybiAwO1xufVxuZnVuY3Rpb24gaXNCdWZmZXIoYikge1xuICBpZiAoZ2xvYmFsLkJ1ZmZlciAmJiB0eXBlb2YgZ2xvYmFsLkJ1ZmZlci5pc0J1ZmZlciA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHJldHVybiBnbG9iYWwuQnVmZmVyLmlzQnVmZmVyKGIpO1xuICB9XG4gIHJldHVybiAhIShiICE9IG51bGwgJiYgYi5faXNCdWZmZXIpO1xufVxuXG4vLyBiYXNlZCBvbiBub2RlIGFzc2VydCwgb3JpZ2luYWwgbm90aWNlOlxuXG4vLyBodHRwOi8vd2lraS5jb21tb25qcy5vcmcvd2lraS9Vbml0X1Rlc3RpbmcvMS4wXG4vL1xuLy8gVEhJUyBJUyBOT1QgVEVTVEVEIE5PUiBMSUtFTFkgVE8gV09SSyBPVVRTSURFIFY4IVxuLy9cbi8vIE9yaWdpbmFsbHkgZnJvbSBuYXJ3aGFsLmpzIChodHRwOi8vbmFyd2hhbGpzLm9yZylcbi8vIENvcHlyaWdodCAoYykgMjAwOSBUaG9tYXMgUm9iaW5zb24gPDI4MG5vcnRoLmNvbT5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5XG4vLyBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSAnU29mdHdhcmUnKSwgdG9cbi8vIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlXG4vLyByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Jcbi8vIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXG4vLyBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgJ0FTIElTJywgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTUyBPUlxuLy8gSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFksXG4vLyBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcbi8vIEFVVEhPUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOXG4vLyBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OXG4vLyBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxudmFyIHV0aWwgPSByZXF1aXJlKCd1dGlsLycpO1xudmFyIGhhc093biA9IE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHk7XG52YXIgcFNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xudmFyIGZ1bmN0aW9uc0hhdmVOYW1lcyA9IChmdW5jdGlvbiAoKSB7XG4gIHJldHVybiBmdW5jdGlvbiBmb28oKSB7fS5uYW1lID09PSAnZm9vJztcbn0oKSk7XG5mdW5jdGlvbiBwVG9TdHJpbmcgKG9iaikge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaik7XG59XG5mdW5jdGlvbiBpc1ZpZXcoYXJyYnVmKSB7XG4gIGlmIChpc0J1ZmZlcihhcnJidWYpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmICh0eXBlb2YgZ2xvYmFsLkFycmF5QnVmZmVyICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmICh0eXBlb2YgQXJyYXlCdWZmZXIuaXNWaWV3ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIEFycmF5QnVmZmVyLmlzVmlldyhhcnJidWYpO1xuICB9XG4gIGlmICghYXJyYnVmKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIGlmIChhcnJidWYgaW5zdGFuY2VvZiBEYXRhVmlldykge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIGlmIChhcnJidWYuYnVmZmVyICYmIGFycmJ1Zi5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cbi8vIDEuIFRoZSBhc3NlcnQgbW9kdWxlIHByb3ZpZGVzIGZ1bmN0aW9ucyB0aGF0IHRocm93XG4vLyBBc3NlcnRpb25FcnJvcidzIHdoZW4gcGFydGljdWxhciBjb25kaXRpb25zIGFyZSBub3QgbWV0LiBUaGVcbi8vIGFzc2VydCBtb2R1bGUgbXVzdCBjb25mb3JtIHRvIHRoZSBmb2xsb3dpbmcgaW50ZXJmYWNlLlxuXG52YXIgYXNzZXJ0ID0gbW9kdWxlLmV4cG9ydHMgPSBvaztcblxuLy8gMi4gVGhlIEFzc2VydGlvbkVycm9yIGlzIGRlZmluZWQgaW4gYXNzZXJ0LlxuLy8gbmV3IGFzc2VydC5Bc3NlcnRpb25FcnJvcih7IG1lc3NhZ2U6IG1lc3NhZ2UsXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYWN0dWFsOiBhY3R1YWwsXG4vLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwZWN0ZWQ6IGV4cGVjdGVkIH0pXG5cbnZhciByZWdleCA9IC9cXHMqZnVuY3Rpb25cXHMrKFteXFwoXFxzXSopXFxzKi87XG4vLyBiYXNlZCBvbiBodHRwczovL2dpdGh1Yi5jb20vbGpoYXJiL2Z1bmN0aW9uLnByb3RvdHlwZS5uYW1lL2Jsb2IvYWRlZWVlYzhiZmNjNjA2OGIxODdkN2Q5ZmIzZDViYjFkM2EzMDg5OS9pbXBsZW1lbnRhdGlvbi5qc1xuZnVuY3Rpb24gZ2V0TmFtZShmdW5jKSB7XG4gIGlmICghdXRpbC5pc0Z1bmN0aW9uKGZ1bmMpKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIGlmIChmdW5jdGlvbnNIYXZlTmFtZXMpIHtcbiAgICByZXR1cm4gZnVuYy5uYW1lO1xuICB9XG4gIHZhciBzdHIgPSBmdW5jLnRvU3RyaW5nKCk7XG4gIHZhciBtYXRjaCA9IHN0ci5tYXRjaChyZWdleCk7XG4gIHJldHVybiBtYXRjaCAmJiBtYXRjaFsxXTtcbn1cbmFzc2VydC5Bc3NlcnRpb25FcnJvciA9IGZ1bmN0aW9uIEFzc2VydGlvbkVycm9yKG9wdGlvbnMpIHtcbiAgdGhpcy5uYW1lID0gJ0Fzc2VydGlvbkVycm9yJztcbiAgdGhpcy5hY3R1YWwgPSBvcHRpb25zLmFjdHVhbDtcbiAgdGhpcy5leHBlY3RlZCA9IG9wdGlvbnMuZXhwZWN0ZWQ7XG4gIHRoaXMub3BlcmF0b3IgPSBvcHRpb25zLm9wZXJhdG9yO1xuICBpZiAob3B0aW9ucy5tZXNzYWdlKSB7XG4gICAgdGhpcy5tZXNzYWdlID0gb3B0aW9ucy5tZXNzYWdlO1xuICAgIHRoaXMuZ2VuZXJhdGVkTWVzc2FnZSA9IGZhbHNlO1xuICB9IGVsc2Uge1xuICAgIHRoaXMubWVzc2FnZSA9IGdldE1lc3NhZ2UodGhpcyk7XG4gICAgdGhpcy5nZW5lcmF0ZWRNZXNzYWdlID0gdHJ1ZTtcbiAgfVxuICB2YXIgc3RhY2tTdGFydEZ1bmN0aW9uID0gb3B0aW9ucy5zdGFja1N0YXJ0RnVuY3Rpb24gfHwgZmFpbDtcbiAgaWYgKEVycm9yLmNhcHR1cmVTdGFja1RyYWNlKSB7XG4gICAgRXJyb3IuY2FwdHVyZVN0YWNrVHJhY2UodGhpcywgc3RhY2tTdGFydEZ1bmN0aW9uKTtcbiAgfSBlbHNlIHtcbiAgICAvLyBub24gdjggYnJvd3NlcnMgc28gd2UgY2FuIGhhdmUgYSBzdGFja3RyYWNlXG4gICAgdmFyIGVyciA9IG5ldyBFcnJvcigpO1xuICAgIGlmIChlcnIuc3RhY2spIHtcbiAgICAgIHZhciBvdXQgPSBlcnIuc3RhY2s7XG5cbiAgICAgIC8vIHRyeSB0byBzdHJpcCB1c2VsZXNzIGZyYW1lc1xuICAgICAgdmFyIGZuX25hbWUgPSBnZXROYW1lKHN0YWNrU3RhcnRGdW5jdGlvbik7XG4gICAgICB2YXIgaWR4ID0gb3V0LmluZGV4T2YoJ1xcbicgKyBmbl9uYW1lKTtcbiAgICAgIGlmIChpZHggPj0gMCkge1xuICAgICAgICAvLyBvbmNlIHdlIGhhdmUgbG9jYXRlZCB0aGUgZnVuY3Rpb24gZnJhbWVcbiAgICAgICAgLy8gd2UgbmVlZCB0byBzdHJpcCBvdXQgZXZlcnl0aGluZyBiZWZvcmUgaXQgKGFuZCBpdHMgbGluZSlcbiAgICAgICAgdmFyIG5leHRfbGluZSA9IG91dC5pbmRleE9mKCdcXG4nLCBpZHggKyAxKTtcbiAgICAgICAgb3V0ID0gb3V0LnN1YnN0cmluZyhuZXh0X2xpbmUgKyAxKTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5zdGFjayA9IG91dDtcbiAgICB9XG4gIH1cbn07XG5cbi8vIGFzc2VydC5Bc3NlcnRpb25FcnJvciBpbnN0YW5jZW9mIEVycm9yXG51dGlsLmluaGVyaXRzKGFzc2VydC5Bc3NlcnRpb25FcnJvciwgRXJyb3IpO1xuXG5mdW5jdGlvbiB0cnVuY2F0ZShzLCBuKSB7XG4gIGlmICh0eXBlb2YgcyA9PT0gJ3N0cmluZycpIHtcbiAgICByZXR1cm4gcy5sZW5ndGggPCBuID8gcyA6IHMuc2xpY2UoMCwgbik7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIHM7XG4gIH1cbn1cbmZ1bmN0aW9uIGluc3BlY3Qoc29tZXRoaW5nKSB7XG4gIGlmIChmdW5jdGlvbnNIYXZlTmFtZXMgfHwgIXV0aWwuaXNGdW5jdGlvbihzb21ldGhpbmcpKSB7XG4gICAgcmV0dXJuIHV0aWwuaW5zcGVjdChzb21ldGhpbmcpO1xuICB9XG4gIHZhciByYXduYW1lID0gZ2V0TmFtZShzb21ldGhpbmcpO1xuICB2YXIgbmFtZSA9IHJhd25hbWUgPyAnOiAnICsgcmF3bmFtZSA6ICcnO1xuICByZXR1cm4gJ1tGdW5jdGlvbicgKyAgbmFtZSArICddJztcbn1cbmZ1bmN0aW9uIGdldE1lc3NhZ2Uoc2VsZikge1xuICByZXR1cm4gdHJ1bmNhdGUoaW5zcGVjdChzZWxmLmFjdHVhbCksIDEyOCkgKyAnICcgK1xuICAgICAgICAgc2VsZi5vcGVyYXRvciArICcgJyArXG4gICAgICAgICB0cnVuY2F0ZShpbnNwZWN0KHNlbGYuZXhwZWN0ZWQpLCAxMjgpO1xufVxuXG4vLyBBdCBwcmVzZW50IG9ubHkgdGhlIHRocmVlIGtleXMgbWVudGlvbmVkIGFib3ZlIGFyZSB1c2VkIGFuZFxuLy8gdW5kZXJzdG9vZCBieSB0aGUgc3BlYy4gSW1wbGVtZW50YXRpb25zIG9yIHN1YiBtb2R1bGVzIGNhbiBwYXNzXG4vLyBvdGhlciBrZXlzIHRvIHRoZSBBc3NlcnRpb25FcnJvcidzIGNvbnN0cnVjdG9yIC0gdGhleSB3aWxsIGJlXG4vLyBpZ25vcmVkLlxuXG4vLyAzLiBBbGwgb2YgdGhlIGZvbGxvd2luZyBmdW5jdGlvbnMgbXVzdCB0aHJvdyBhbiBBc3NlcnRpb25FcnJvclxuLy8gd2hlbiBhIGNvcnJlc3BvbmRpbmcgY29uZGl0aW9uIGlzIG5vdCBtZXQsIHdpdGggYSBtZXNzYWdlIHRoYXRcbi8vIG1heSBiZSB1bmRlZmluZWQgaWYgbm90IHByb3ZpZGVkLiAgQWxsIGFzc2VydGlvbiBtZXRob2RzIHByb3ZpZGVcbi8vIGJvdGggdGhlIGFjdHVhbCBhbmQgZXhwZWN0ZWQgdmFsdWVzIHRvIHRoZSBhc3NlcnRpb24gZXJyb3IgZm9yXG4vLyBkaXNwbGF5IHB1cnBvc2VzLlxuXG5mdW5jdGlvbiBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsIG9wZXJhdG9yLCBzdGFja1N0YXJ0RnVuY3Rpb24pIHtcbiAgdGhyb3cgbmV3IGFzc2VydC5Bc3NlcnRpb25FcnJvcih7XG4gICAgbWVzc2FnZTogbWVzc2FnZSxcbiAgICBhY3R1YWw6IGFjdHVhbCxcbiAgICBleHBlY3RlZDogZXhwZWN0ZWQsXG4gICAgb3BlcmF0b3I6IG9wZXJhdG9yLFxuICAgIHN0YWNrU3RhcnRGdW5jdGlvbjogc3RhY2tTdGFydEZ1bmN0aW9uXG4gIH0pO1xufVxuXG4vLyBFWFRFTlNJT04hIGFsbG93cyBmb3Igd2VsbCBiZWhhdmVkIGVycm9ycyBkZWZpbmVkIGVsc2V3aGVyZS5cbmFzc2VydC5mYWlsID0gZmFpbDtcblxuLy8gNC4gUHVyZSBhc3NlcnRpb24gdGVzdHMgd2hldGhlciBhIHZhbHVlIGlzIHRydXRoeSwgYXMgZGV0ZXJtaW5lZFxuLy8gYnkgISFndWFyZC5cbi8vIGFzc2VydC5vayhndWFyZCwgbWVzc2FnZV9vcHQpO1xuLy8gVGhpcyBzdGF0ZW1lbnQgaXMgZXF1aXZhbGVudCB0byBhc3NlcnQuZXF1YWwodHJ1ZSwgISFndWFyZCxcbi8vIG1lc3NhZ2Vfb3B0KTsuIFRvIHRlc3Qgc3RyaWN0bHkgZm9yIHRoZSB2YWx1ZSB0cnVlLCB1c2Vcbi8vIGFzc2VydC5zdHJpY3RFcXVhbCh0cnVlLCBndWFyZCwgbWVzc2FnZV9vcHQpOy5cblxuZnVuY3Rpb24gb2sodmFsdWUsIG1lc3NhZ2UpIHtcbiAgaWYgKCF2YWx1ZSkgZmFpbCh2YWx1ZSwgdHJ1ZSwgbWVzc2FnZSwgJz09JywgYXNzZXJ0Lm9rKTtcbn1cbmFzc2VydC5vayA9IG9rO1xuXG4vLyA1LiBUaGUgZXF1YWxpdHkgYXNzZXJ0aW9uIHRlc3RzIHNoYWxsb3csIGNvZXJjaXZlIGVxdWFsaXR5IHdpdGhcbi8vID09LlxuLy8gYXNzZXJ0LmVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2Vfb3B0KTtcblxuYXNzZXJ0LmVxdWFsID0gZnVuY3Rpb24gZXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICBpZiAoYWN0dWFsICE9IGV4cGVjdGVkKSBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsICc9PScsIGFzc2VydC5lcXVhbCk7XG59O1xuXG4vLyA2LiBUaGUgbm9uLWVxdWFsaXR5IGFzc2VydGlvbiB0ZXN0cyBmb3Igd2hldGhlciB0d28gb2JqZWN0cyBhcmUgbm90IGVxdWFsXG4vLyB3aXRoICE9IGFzc2VydC5ub3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlX29wdCk7XG5cbmFzc2VydC5ub3RFcXVhbCA9IGZ1bmN0aW9uIG5vdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgaWYgKGFjdHVhbCA9PSBleHBlY3RlZCkge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgJyE9JywgYXNzZXJ0Lm5vdEVxdWFsKTtcbiAgfVxufTtcblxuLy8gNy4gVGhlIGVxdWl2YWxlbmNlIGFzc2VydGlvbiB0ZXN0cyBhIGRlZXAgZXF1YWxpdHkgcmVsYXRpb24uXG4vLyBhc3NlcnQuZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2Vfb3B0KTtcblxuYXNzZXJ0LmRlZXBFcXVhbCA9IGZ1bmN0aW9uIGRlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIGlmICghX2RlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBmYWxzZSkpIHtcbiAgICBmYWlsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UsICdkZWVwRXF1YWwnLCBhc3NlcnQuZGVlcEVxdWFsKTtcbiAgfVxufTtcblxuYXNzZXJ0LmRlZXBTdHJpY3RFcXVhbCA9IGZ1bmN0aW9uIGRlZXBTdHJpY3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIGlmICghX2RlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCB0cnVlKSkge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgJ2RlZXBTdHJpY3RFcXVhbCcsIGFzc2VydC5kZWVwU3RyaWN0RXF1YWwpO1xuICB9XG59O1xuXG5mdW5jdGlvbiBfZGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIHN0cmljdCwgbWVtb3MpIHtcbiAgLy8gNy4xLiBBbGwgaWRlbnRpY2FsIHZhbHVlcyBhcmUgZXF1aXZhbGVudCwgYXMgZGV0ZXJtaW5lZCBieSA9PT0uXG4gIGlmIChhY3R1YWwgPT09IGV4cGVjdGVkKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH0gZWxzZSBpZiAoaXNCdWZmZXIoYWN0dWFsKSAmJiBpc0J1ZmZlcihleHBlY3RlZCkpIHtcbiAgICByZXR1cm4gY29tcGFyZShhY3R1YWwsIGV4cGVjdGVkKSA9PT0gMDtcblxuICAvLyA3LjIuIElmIHRoZSBleHBlY3RlZCB2YWx1ZSBpcyBhIERhdGUgb2JqZWN0LCB0aGUgYWN0dWFsIHZhbHVlIGlzXG4gIC8vIGVxdWl2YWxlbnQgaWYgaXQgaXMgYWxzbyBhIERhdGUgb2JqZWN0IHRoYXQgcmVmZXJzIHRvIHRoZSBzYW1lIHRpbWUuXG4gIH0gZWxzZSBpZiAodXRpbC5pc0RhdGUoYWN0dWFsKSAmJiB1dGlsLmlzRGF0ZShleHBlY3RlZCkpIHtcbiAgICByZXR1cm4gYWN0dWFsLmdldFRpbWUoKSA9PT0gZXhwZWN0ZWQuZ2V0VGltZSgpO1xuXG4gIC8vIDcuMyBJZiB0aGUgZXhwZWN0ZWQgdmFsdWUgaXMgYSBSZWdFeHAgb2JqZWN0LCB0aGUgYWN0dWFsIHZhbHVlIGlzXG4gIC8vIGVxdWl2YWxlbnQgaWYgaXQgaXMgYWxzbyBhIFJlZ0V4cCBvYmplY3Qgd2l0aCB0aGUgc2FtZSBzb3VyY2UgYW5kXG4gIC8vIHByb3BlcnRpZXMgKGBnbG9iYWxgLCBgbXVsdGlsaW5lYCwgYGxhc3RJbmRleGAsIGBpZ25vcmVDYXNlYCkuXG4gIH0gZWxzZSBpZiAodXRpbC5pc1JlZ0V4cChhY3R1YWwpICYmIHV0aWwuaXNSZWdFeHAoZXhwZWN0ZWQpKSB7XG4gICAgcmV0dXJuIGFjdHVhbC5zb3VyY2UgPT09IGV4cGVjdGVkLnNvdXJjZSAmJlxuICAgICAgICAgICBhY3R1YWwuZ2xvYmFsID09PSBleHBlY3RlZC5nbG9iYWwgJiZcbiAgICAgICAgICAgYWN0dWFsLm11bHRpbGluZSA9PT0gZXhwZWN0ZWQubXVsdGlsaW5lICYmXG4gICAgICAgICAgIGFjdHVhbC5sYXN0SW5kZXggPT09IGV4cGVjdGVkLmxhc3RJbmRleCAmJlxuICAgICAgICAgICBhY3R1YWwuaWdub3JlQ2FzZSA9PT0gZXhwZWN0ZWQuaWdub3JlQ2FzZTtcblxuICAvLyA3LjQuIE90aGVyIHBhaXJzIHRoYXQgZG8gbm90IGJvdGggcGFzcyB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCcsXG4gIC8vIGVxdWl2YWxlbmNlIGlzIGRldGVybWluZWQgYnkgPT0uXG4gIH0gZWxzZSBpZiAoKGFjdHVhbCA9PT0gbnVsbCB8fCB0eXBlb2YgYWN0dWFsICE9PSAnb2JqZWN0JykgJiZcbiAgICAgICAgICAgICAoZXhwZWN0ZWQgPT09IG51bGwgfHwgdHlwZW9mIGV4cGVjdGVkICE9PSAnb2JqZWN0JykpIHtcbiAgICByZXR1cm4gc3RyaWN0ID8gYWN0dWFsID09PSBleHBlY3RlZCA6IGFjdHVhbCA9PSBleHBlY3RlZDtcblxuICAvLyBJZiBib3RoIHZhbHVlcyBhcmUgaW5zdGFuY2VzIG9mIHR5cGVkIGFycmF5cywgd3JhcCB0aGVpciB1bmRlcmx5aW5nXG4gIC8vIEFycmF5QnVmZmVycyBpbiBhIEJ1ZmZlciBlYWNoIHRvIGluY3JlYXNlIHBlcmZvcm1hbmNlXG4gIC8vIFRoaXMgb3B0aW1pemF0aW9uIHJlcXVpcmVzIHRoZSBhcnJheXMgdG8gaGF2ZSB0aGUgc2FtZSB0eXBlIGFzIGNoZWNrZWQgYnlcbiAgLy8gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZyAoYWthIHBUb1N0cmluZykuIE5ldmVyIHBlcmZvcm0gYmluYXJ5XG4gIC8vIGNvbXBhcmlzb25zIGZvciBGbG9hdCpBcnJheXMsIHRob3VnaCwgc2luY2UgZS5nLiArMCA9PT0gLTAgYnV0IHRoZWlyXG4gIC8vIGJpdCBwYXR0ZXJucyBhcmUgbm90IGlkZW50aWNhbC5cbiAgfSBlbHNlIGlmIChpc1ZpZXcoYWN0dWFsKSAmJiBpc1ZpZXcoZXhwZWN0ZWQpICYmXG4gICAgICAgICAgICAgcFRvU3RyaW5nKGFjdHVhbCkgPT09IHBUb1N0cmluZyhleHBlY3RlZCkgJiZcbiAgICAgICAgICAgICAhKGFjdHVhbCBpbnN0YW5jZW9mIEZsb2F0MzJBcnJheSB8fFxuICAgICAgICAgICAgICAgYWN0dWFsIGluc3RhbmNlb2YgRmxvYXQ2NEFycmF5KSkge1xuICAgIHJldHVybiBjb21wYXJlKG5ldyBVaW50OEFycmF5KGFjdHVhbC5idWZmZXIpLFxuICAgICAgICAgICAgICAgICAgIG5ldyBVaW50OEFycmF5KGV4cGVjdGVkLmJ1ZmZlcikpID09PSAwO1xuXG4gIC8vIDcuNSBGb3IgYWxsIG90aGVyIE9iamVjdCBwYWlycywgaW5jbHVkaW5nIEFycmF5IG9iamVjdHMsIGVxdWl2YWxlbmNlIGlzXG4gIC8vIGRldGVybWluZWQgYnkgaGF2aW5nIHRoZSBzYW1lIG51bWJlciBvZiBvd25lZCBwcm9wZXJ0aWVzIChhcyB2ZXJpZmllZFxuICAvLyB3aXRoIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCksIHRoZSBzYW1lIHNldCBvZiBrZXlzXG4gIC8vIChhbHRob3VnaCBub3QgbmVjZXNzYXJpbHkgdGhlIHNhbWUgb3JkZXIpLCBlcXVpdmFsZW50IHZhbHVlcyBmb3IgZXZlcnlcbiAgLy8gY29ycmVzcG9uZGluZyBrZXksIGFuZCBhbiBpZGVudGljYWwgJ3Byb3RvdHlwZScgcHJvcGVydHkuIE5vdGU6IHRoaXNcbiAgLy8gYWNjb3VudHMgZm9yIGJvdGggbmFtZWQgYW5kIGluZGV4ZWQgcHJvcGVydGllcyBvbiBBcnJheXMuXG4gIH0gZWxzZSBpZiAoaXNCdWZmZXIoYWN0dWFsKSAhPT0gaXNCdWZmZXIoZXhwZWN0ZWQpKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9IGVsc2Uge1xuICAgIG1lbW9zID0gbWVtb3MgfHwge2FjdHVhbDogW10sIGV4cGVjdGVkOiBbXX07XG5cbiAgICB2YXIgYWN0dWFsSW5kZXggPSBtZW1vcy5hY3R1YWwuaW5kZXhPZihhY3R1YWwpO1xuICAgIGlmIChhY3R1YWxJbmRleCAhPT0gLTEpIHtcbiAgICAgIGlmIChhY3R1YWxJbmRleCA9PT0gbWVtb3MuZXhwZWN0ZWQuaW5kZXhPZihleHBlY3RlZCkpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9XG4gICAgfVxuXG4gICAgbWVtb3MuYWN0dWFsLnB1c2goYWN0dWFsKTtcbiAgICBtZW1vcy5leHBlY3RlZC5wdXNoKGV4cGVjdGVkKTtcblxuICAgIHJldHVybiBvYmpFcXVpdihhY3R1YWwsIGV4cGVjdGVkLCBzdHJpY3QsIG1lbW9zKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpc0FyZ3VtZW50cyhvYmplY3QpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChvYmplY3QpID09ICdbb2JqZWN0IEFyZ3VtZW50c10nO1xufVxuXG5mdW5jdGlvbiBvYmpFcXVpdihhLCBiLCBzdHJpY3QsIGFjdHVhbFZpc2l0ZWRPYmplY3RzKSB7XG4gIGlmIChhID09PSBudWxsIHx8IGEgPT09IHVuZGVmaW5lZCB8fCBiID09PSBudWxsIHx8IGIgPT09IHVuZGVmaW5lZClcbiAgICByZXR1cm4gZmFsc2U7XG4gIC8vIGlmIG9uZSBpcyBhIHByaW1pdGl2ZSwgdGhlIG90aGVyIG11c3QgYmUgc2FtZVxuICBpZiAodXRpbC5pc1ByaW1pdGl2ZShhKSB8fCB1dGlsLmlzUHJpbWl0aXZlKGIpKVxuICAgIHJldHVybiBhID09PSBiO1xuICBpZiAoc3RyaWN0ICYmIE9iamVjdC5nZXRQcm90b3R5cGVPZihhKSAhPT0gT2JqZWN0LmdldFByb3RvdHlwZU9mKGIpKVxuICAgIHJldHVybiBmYWxzZTtcbiAgdmFyIGFJc0FyZ3MgPSBpc0FyZ3VtZW50cyhhKTtcbiAgdmFyIGJJc0FyZ3MgPSBpc0FyZ3VtZW50cyhiKTtcbiAgaWYgKChhSXNBcmdzICYmICFiSXNBcmdzKSB8fCAoIWFJc0FyZ3MgJiYgYklzQXJncykpXG4gICAgcmV0dXJuIGZhbHNlO1xuICBpZiAoYUlzQXJncykge1xuICAgIGEgPSBwU2xpY2UuY2FsbChhKTtcbiAgICBiID0gcFNsaWNlLmNhbGwoYik7XG4gICAgcmV0dXJuIF9kZWVwRXF1YWwoYSwgYiwgc3RyaWN0KTtcbiAgfVxuICB2YXIga2EgPSBvYmplY3RLZXlzKGEpO1xuICB2YXIga2IgPSBvYmplY3RLZXlzKGIpO1xuICB2YXIga2V5LCBpO1xuICAvLyBoYXZpbmcgdGhlIHNhbWUgbnVtYmVyIG9mIG93bmVkIHByb3BlcnRpZXMgKGtleXMgaW5jb3Jwb3JhdGVzXG4gIC8vIGhhc093blByb3BlcnR5KVxuICBpZiAoa2EubGVuZ3RoICE9PSBrYi5sZW5ndGgpXG4gICAgcmV0dXJuIGZhbHNlO1xuICAvL3RoZSBzYW1lIHNldCBvZiBrZXlzIChhbHRob3VnaCBub3QgbmVjZXNzYXJpbHkgdGhlIHNhbWUgb3JkZXIpLFxuICBrYS5zb3J0KCk7XG4gIGtiLnNvcnQoKTtcbiAgLy9+fn5jaGVhcCBrZXkgdGVzdFxuICBmb3IgKGkgPSBrYS5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgIGlmIChrYVtpXSAhPT0ga2JbaV0pXG4gICAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgLy9lcXVpdmFsZW50IHZhbHVlcyBmb3IgZXZlcnkgY29ycmVzcG9uZGluZyBrZXksIGFuZFxuICAvL35+fnBvc3NpYmx5IGV4cGVuc2l2ZSBkZWVwIHRlc3RcbiAgZm9yIChpID0ga2EubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBrZXkgPSBrYVtpXTtcbiAgICBpZiAoIV9kZWVwRXF1YWwoYVtrZXldLCBiW2tleV0sIHN0cmljdCwgYWN0dWFsVmlzaXRlZE9iamVjdHMpKVxuICAgICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIHJldHVybiB0cnVlO1xufVxuXG4vLyA4LiBUaGUgbm9uLWVxdWl2YWxlbmNlIGFzc2VydGlvbiB0ZXN0cyBmb3IgYW55IGRlZXAgaW5lcXVhbGl0eS5cbi8vIGFzc2VydC5ub3REZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZV9vcHQpO1xuXG5hc3NlcnQubm90RGVlcEVxdWFsID0gZnVuY3Rpb24gbm90RGVlcEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2UpIHtcbiAgaWYgKF9kZWVwRXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgZmFsc2UpKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCAnbm90RGVlcEVxdWFsJywgYXNzZXJ0Lm5vdERlZXBFcXVhbCk7XG4gIH1cbn07XG5cbmFzc2VydC5ub3REZWVwU3RyaWN0RXF1YWwgPSBub3REZWVwU3RyaWN0RXF1YWw7XG5mdW5jdGlvbiBub3REZWVwU3RyaWN0RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICBpZiAoX2RlZXBFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCB0cnVlKSkge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgJ25vdERlZXBTdHJpY3RFcXVhbCcsIG5vdERlZXBTdHJpY3RFcXVhbCk7XG4gIH1cbn1cblxuXG4vLyA5LiBUaGUgc3RyaWN0IGVxdWFsaXR5IGFzc2VydGlvbiB0ZXN0cyBzdHJpY3QgZXF1YWxpdHksIGFzIGRldGVybWluZWQgYnkgPT09LlxuLy8gYXNzZXJ0LnN0cmljdEVxdWFsKGFjdHVhbCwgZXhwZWN0ZWQsIG1lc3NhZ2Vfb3B0KTtcblxuYXNzZXJ0LnN0cmljdEVxdWFsID0gZnVuY3Rpb24gc3RyaWN0RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSkge1xuICBpZiAoYWN0dWFsICE9PSBleHBlY3RlZCkge1xuICAgIGZhaWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZSwgJz09PScsIGFzc2VydC5zdHJpY3RFcXVhbCk7XG4gIH1cbn07XG5cbi8vIDEwLiBUaGUgc3RyaWN0IG5vbi1lcXVhbGl0eSBhc3NlcnRpb24gdGVzdHMgZm9yIHN0cmljdCBpbmVxdWFsaXR5LCBhc1xuLy8gZGV0ZXJtaW5lZCBieSAhPT0uICBhc3NlcnQubm90U3RyaWN0RXF1YWwoYWN0dWFsLCBleHBlY3RlZCwgbWVzc2FnZV9vcHQpO1xuXG5hc3NlcnQubm90U3RyaWN0RXF1YWwgPSBmdW5jdGlvbiBub3RTdHJpY3RFcXVhbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIGlmIChhY3R1YWwgPT09IGV4cGVjdGVkKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCBtZXNzYWdlLCAnIT09JywgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsKTtcbiAgfVxufTtcblxuZnVuY3Rpb24gZXhwZWN0ZWRFeGNlcHRpb24oYWN0dWFsLCBleHBlY3RlZCkge1xuICBpZiAoIWFjdHVhbCB8fCAhZXhwZWN0ZWQpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGV4cGVjdGVkKSA9PSAnW29iamVjdCBSZWdFeHBdJykge1xuICAgIHJldHVybiBleHBlY3RlZC50ZXN0KGFjdHVhbCk7XG4gIH1cblxuICB0cnkge1xuICAgIGlmIChhY3R1YWwgaW5zdGFuY2VvZiBleHBlY3RlZCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgLy8gSWdub3JlLiAgVGhlIGluc3RhbmNlb2YgY2hlY2sgZG9lc24ndCB3b3JrIGZvciBhcnJvdyBmdW5jdGlvbnMuXG4gIH1cblxuICBpZiAoRXJyb3IuaXNQcm90b3R5cGVPZihleHBlY3RlZCkpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICByZXR1cm4gZXhwZWN0ZWQuY2FsbCh7fSwgYWN0dWFsKSA9PT0gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gX3RyeUJsb2NrKGJsb2NrKSB7XG4gIHZhciBlcnJvcjtcbiAgdHJ5IHtcbiAgICBibG9jaygpO1xuICB9IGNhdGNoIChlKSB7XG4gICAgZXJyb3IgPSBlO1xuICB9XG4gIHJldHVybiBlcnJvcjtcbn1cblxuZnVuY3Rpb24gX3Rocm93cyhzaG91bGRUaHJvdywgYmxvY2ssIGV4cGVjdGVkLCBtZXNzYWdlKSB7XG4gIHZhciBhY3R1YWw7XG5cbiAgaWYgKHR5cGVvZiBibG9jayAhPT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiYmxvY2tcIiBhcmd1bWVudCBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgfVxuXG4gIGlmICh0eXBlb2YgZXhwZWN0ZWQgPT09ICdzdHJpbmcnKSB7XG4gICAgbWVzc2FnZSA9IGV4cGVjdGVkO1xuICAgIGV4cGVjdGVkID0gbnVsbDtcbiAgfVxuXG4gIGFjdHVhbCA9IF90cnlCbG9jayhibG9jayk7XG5cbiAgbWVzc2FnZSA9IChleHBlY3RlZCAmJiBleHBlY3RlZC5uYW1lID8gJyAoJyArIGV4cGVjdGVkLm5hbWUgKyAnKS4nIDogJy4nKSArXG4gICAgICAgICAgICAobWVzc2FnZSA/ICcgJyArIG1lc3NhZ2UgOiAnLicpO1xuXG4gIGlmIChzaG91bGRUaHJvdyAmJiAhYWN0dWFsKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCAnTWlzc2luZyBleHBlY3RlZCBleGNlcHRpb24nICsgbWVzc2FnZSk7XG4gIH1cblxuICB2YXIgdXNlclByb3ZpZGVkTWVzc2FnZSA9IHR5cGVvZiBtZXNzYWdlID09PSAnc3RyaW5nJztcbiAgdmFyIGlzVW53YW50ZWRFeGNlcHRpb24gPSAhc2hvdWxkVGhyb3cgJiYgdXRpbC5pc0Vycm9yKGFjdHVhbCk7XG4gIHZhciBpc1VuZXhwZWN0ZWRFeGNlcHRpb24gPSAhc2hvdWxkVGhyb3cgJiYgYWN0dWFsICYmICFleHBlY3RlZDtcblxuICBpZiAoKGlzVW53YW50ZWRFeGNlcHRpb24gJiZcbiAgICAgIHVzZXJQcm92aWRlZE1lc3NhZ2UgJiZcbiAgICAgIGV4cGVjdGVkRXhjZXB0aW9uKGFjdHVhbCwgZXhwZWN0ZWQpKSB8fFxuICAgICAgaXNVbmV4cGVjdGVkRXhjZXB0aW9uKSB7XG4gICAgZmFpbChhY3R1YWwsIGV4cGVjdGVkLCAnR290IHVud2FudGVkIGV4Y2VwdGlvbicgKyBtZXNzYWdlKTtcbiAgfVxuXG4gIGlmICgoc2hvdWxkVGhyb3cgJiYgYWN0dWFsICYmIGV4cGVjdGVkICYmXG4gICAgICAhZXhwZWN0ZWRFeGNlcHRpb24oYWN0dWFsLCBleHBlY3RlZCkpIHx8ICghc2hvdWxkVGhyb3cgJiYgYWN0dWFsKSkge1xuICAgIHRocm93IGFjdHVhbDtcbiAgfVxufVxuXG4vLyAxMS4gRXhwZWN0ZWQgdG8gdGhyb3cgYW4gZXJyb3I6XG4vLyBhc3NlcnQudGhyb3dzKGJsb2NrLCBFcnJvcl9vcHQsIG1lc3NhZ2Vfb3B0KTtcblxuYXNzZXJ0LnRocm93cyA9IGZ1bmN0aW9uKGJsb2NrLCAvKm9wdGlvbmFsKi9lcnJvciwgLypvcHRpb25hbCovbWVzc2FnZSkge1xuICBfdGhyb3dzKHRydWUsIGJsb2NrLCBlcnJvciwgbWVzc2FnZSk7XG59O1xuXG4vLyBFWFRFTlNJT04hIFRoaXMgaXMgYW5ub3lpbmcgdG8gd3JpdGUgb3V0c2lkZSB0aGlzIG1vZHVsZS5cbmFzc2VydC5kb2VzTm90VGhyb3cgPSBmdW5jdGlvbihibG9jaywgLypvcHRpb25hbCovZXJyb3IsIC8qb3B0aW9uYWwqL21lc3NhZ2UpIHtcbiAgX3Rocm93cyhmYWxzZSwgYmxvY2ssIGVycm9yLCBtZXNzYWdlKTtcbn07XG5cbmFzc2VydC5pZkVycm9yID0gZnVuY3Rpb24oZXJyKSB7IGlmIChlcnIpIHRocm93IGVycjsgfTtcblxudmFyIG9iamVjdEtleXMgPSBPYmplY3Qua2V5cyB8fCBmdW5jdGlvbiAob2JqKSB7XG4gIHZhciBrZXlzID0gW107XG4gIGZvciAodmFyIGtleSBpbiBvYmopIHtcbiAgICBpZiAoaGFzT3duLmNhbGwob2JqLCBrZXkpKSBrZXlzLnB1c2goa2V5KTtcbiAgfVxuICByZXR1cm4ga2V5cztcbn07XG4iLCIvLyBiYXNlLXggZW5jb2Rpbmdcbi8vIEZvcmtlZCBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS9jcnlwdG9jb2luanMvYnM1OFxuLy8gT3JpZ2luYWxseSB3cml0dGVuIGJ5IE1pa2UgSGVhcm4gZm9yIEJpdGNvaW5KXG4vLyBDb3B5cmlnaHQgKGMpIDIwMTEgR29vZ2xlIEluY1xuLy8gUG9ydGVkIHRvIEphdmFTY3JpcHQgYnkgU3RlZmFuIFRob21hc1xuLy8gTWVyZ2VkIEJ1ZmZlciByZWZhY3RvcmluZ3MgZnJvbSBiYXNlNTgtbmF0aXZlIGJ5IFN0ZXBoZW4gUGFpclxuLy8gQ29weXJpZ2h0IChjKSAyMDEzIEJpdFBheSBJbmNcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBiYXNlIChBTFBIQUJFVCkge1xuICB2YXIgQUxQSEFCRVRfTUFQID0ge31cbiAgdmFyIEJBU0UgPSBBTFBIQUJFVC5sZW5ndGhcbiAgdmFyIExFQURFUiA9IEFMUEhBQkVULmNoYXJBdCgwKVxuXG4gIC8vIHByZS1jb21wdXRlIGxvb2t1cCB0YWJsZVxuICBmb3IgKHZhciBpID0gMDsgaSA8IEFMUEhBQkVULmxlbmd0aDsgaSsrKSB7XG4gICAgQUxQSEFCRVRfTUFQW0FMUEhBQkVULmNoYXJBdChpKV0gPSBpXG4gIH1cblxuICBmdW5jdGlvbiBlbmNvZGUgKHNvdXJjZSkge1xuICAgIGlmIChzb3VyY2UubGVuZ3RoID09PSAwKSByZXR1cm4gJydcblxuICAgIHZhciBkaWdpdHMgPSBbMF1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNvdXJjZS5sZW5ndGg7ICsraSkge1xuICAgICAgZm9yICh2YXIgaiA9IDAsIGNhcnJ5ID0gc291cmNlW2ldOyBqIDwgZGlnaXRzLmxlbmd0aDsgKytqKSB7XG4gICAgICAgIGNhcnJ5ICs9IGRpZ2l0c1tqXSA8PCA4XG4gICAgICAgIGRpZ2l0c1tqXSA9IGNhcnJ5ICUgQkFTRVxuICAgICAgICBjYXJyeSA9IChjYXJyeSAvIEJBU0UpIHwgMFxuICAgICAgfVxuXG4gICAgICB3aGlsZSAoY2FycnkgPiAwKSB7XG4gICAgICAgIGRpZ2l0cy5wdXNoKGNhcnJ5ICUgQkFTRSlcbiAgICAgICAgY2FycnkgPSAoY2FycnkgLyBCQVNFKSB8IDBcbiAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc3RyaW5nID0gJydcblxuICAgIC8vIGRlYWwgd2l0aCBsZWFkaW5nIHplcm9zXG4gICAgZm9yICh2YXIgayA9IDA7IHNvdXJjZVtrXSA9PT0gMCAmJiBrIDwgc291cmNlLmxlbmd0aCAtIDE7ICsraykgc3RyaW5nICs9IEFMUEhBQkVUWzBdXG4gICAgLy8gY29udmVydCBkaWdpdHMgdG8gYSBzdHJpbmdcbiAgICBmb3IgKHZhciBxID0gZGlnaXRzLmxlbmd0aCAtIDE7IHEgPj0gMDsgLS1xKSBzdHJpbmcgKz0gQUxQSEFCRVRbZGlnaXRzW3FdXVxuXG4gICAgcmV0dXJuIHN0cmluZ1xuICB9XG5cbiAgZnVuY3Rpb24gZGVjb2RlVW5zYWZlIChzdHJpbmcpIHtcbiAgICBpZiAoc3RyaW5nLmxlbmd0aCA9PT0gMCkgcmV0dXJuIFtdXG5cbiAgICB2YXIgYnl0ZXMgPSBbMF1cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0cmluZy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFyIHZhbHVlID0gQUxQSEFCRVRfTUFQW3N0cmluZ1tpXV1cbiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSByZXR1cm5cblxuICAgICAgZm9yICh2YXIgaiA9IDAsIGNhcnJ5ID0gdmFsdWU7IGogPCBieXRlcy5sZW5ndGg7ICsraikge1xuICAgICAgICBjYXJyeSArPSBieXRlc1tqXSAqIEJBU0VcbiAgICAgICAgYnl0ZXNbal0gPSBjYXJyeSAmIDB4ZmZcbiAgICAgICAgY2FycnkgPj49IDhcbiAgICAgIH1cblxuICAgICAgd2hpbGUgKGNhcnJ5ID4gMCkge1xuICAgICAgICBieXRlcy5wdXNoKGNhcnJ5ICYgMHhmZilcbiAgICAgICAgY2FycnkgPj49IDhcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBkZWFsIHdpdGggbGVhZGluZyB6ZXJvc1xuICAgIGZvciAodmFyIGsgPSAwOyBzdHJpbmdba10gPT09IExFQURFUiAmJiBrIDwgc3RyaW5nLmxlbmd0aCAtIDE7ICsraykge1xuICAgICAgYnl0ZXMucHVzaCgwKVxuICAgIH1cblxuICAgIHJldHVybiBieXRlcy5yZXZlcnNlKClcbiAgfVxuXG4gIGZ1bmN0aW9uIGRlY29kZSAoc3RyaW5nKSB7XG4gICAgdmFyIGFycmF5ID0gZGVjb2RlVW5zYWZlKHN0cmluZylcbiAgICBpZiAoYXJyYXkpIHJldHVybiBhcnJheVxuXG4gICAgdGhyb3cgbmV3IEVycm9yKCdOb24tYmFzZScgKyBCQVNFICsgJyBjaGFyYWN0ZXInKVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBlbmNvZGU6IGVuY29kZSxcbiAgICBkZWNvZGVVbnNhZmU6IGRlY29kZVVuc2FmZSxcbiAgICBkZWNvZGU6IGRlY29kZVxuICB9XG59XG4iLCIndXNlIHN0cmljdCdcblxuZXhwb3J0cy5ieXRlTGVuZ3RoID0gYnl0ZUxlbmd0aFxuZXhwb3J0cy50b0J5dGVBcnJheSA9IHRvQnl0ZUFycmF5XG5leHBvcnRzLmZyb21CeXRlQXJyYXkgPSBmcm9tQnl0ZUFycmF5XG5cbnZhciBsb29rdXAgPSBbXVxudmFyIHJldkxvb2t1cCA9IFtdXG52YXIgQXJyID0gdHlwZW9mIFVpbnQ4QXJyYXkgIT09ICd1bmRlZmluZWQnID8gVWludDhBcnJheSA6IEFycmF5XG5cbnZhciBjb2RlID0gJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky8nXG5mb3IgKHZhciBpID0gMCwgbGVuID0gY29kZS5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICBsb29rdXBbaV0gPSBjb2RlW2ldXG4gIHJldkxvb2t1cFtjb2RlLmNoYXJDb2RlQXQoaSldID0gaVxufVxuXG4vLyBTdXBwb3J0IGRlY29kaW5nIFVSTC1zYWZlIGJhc2U2NCBzdHJpbmdzLCBhcyBOb2RlLmpzIGRvZXMuXG4vLyBTZWU6IGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0Jhc2U2NCNVUkxfYXBwbGljYXRpb25zXG5yZXZMb29rdXBbJy0nLmNoYXJDb2RlQXQoMCldID0gNjJcbnJldkxvb2t1cFsnXycuY2hhckNvZGVBdCgwKV0gPSA2M1xuXG5mdW5jdGlvbiBnZXRMZW5zIChiNjQpIHtcbiAgdmFyIGxlbiA9IGI2NC5sZW5ndGhcblxuICBpZiAobGVuICUgNCA+IDApIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgc3RyaW5nLiBMZW5ndGggbXVzdCBiZSBhIG11bHRpcGxlIG9mIDQnKVxuICB9XG5cbiAgLy8gVHJpbSBvZmYgZXh0cmEgYnl0ZXMgYWZ0ZXIgcGxhY2Vob2xkZXIgYnl0ZXMgYXJlIGZvdW5kXG4gIC8vIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2JlYXRnYW1taXQvYmFzZTY0LWpzL2lzc3Vlcy80MlxuICB2YXIgdmFsaWRMZW4gPSBiNjQuaW5kZXhPZignPScpXG4gIGlmICh2YWxpZExlbiA9PT0gLTEpIHZhbGlkTGVuID0gbGVuXG5cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IHZhbGlkTGVuID09PSBsZW5cbiAgICA/IDBcbiAgICA6IDQgLSAodmFsaWRMZW4gJSA0KVxuXG4gIHJldHVybiBbdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbl1cbn1cblxuLy8gYmFzZTY0IGlzIDQvMyArIHVwIHRvIHR3byBjaGFyYWN0ZXJzIG9mIHRoZSBvcmlnaW5hbCBkYXRhXG5mdW5jdGlvbiBieXRlTGVuZ3RoIChiNjQpIHtcbiAgdmFyIGxlbnMgPSBnZXRMZW5zKGI2NClcbiAgdmFyIHZhbGlkTGVuID0gbGVuc1swXVxuICB2YXIgcGxhY2VIb2xkZXJzTGVuID0gbGVuc1sxXVxuICByZXR1cm4gKCh2YWxpZExlbiArIHBsYWNlSG9sZGVyc0xlbikgKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNMZW5cbn1cblxuZnVuY3Rpb24gX2J5dGVMZW5ndGggKGI2NCwgdmFsaWRMZW4sIHBsYWNlSG9sZGVyc0xlbikge1xuICByZXR1cm4gKCh2YWxpZExlbiArIHBsYWNlSG9sZGVyc0xlbikgKiAzIC8gNCkgLSBwbGFjZUhvbGRlcnNMZW5cbn1cblxuZnVuY3Rpb24gdG9CeXRlQXJyYXkgKGI2NCkge1xuICB2YXIgdG1wXG4gIHZhciBsZW5zID0gZ2V0TGVucyhiNjQpXG4gIHZhciB2YWxpZExlbiA9IGxlbnNbMF1cbiAgdmFyIHBsYWNlSG9sZGVyc0xlbiA9IGxlbnNbMV1cblxuICB2YXIgYXJyID0gbmV3IEFycihfYnl0ZUxlbmd0aChiNjQsIHZhbGlkTGVuLCBwbGFjZUhvbGRlcnNMZW4pKVxuXG4gIHZhciBjdXJCeXRlID0gMFxuXG4gIC8vIGlmIHRoZXJlIGFyZSBwbGFjZWhvbGRlcnMsIG9ubHkgZ2V0IHVwIHRvIHRoZSBsYXN0IGNvbXBsZXRlIDQgY2hhcnNcbiAgdmFyIGxlbiA9IHBsYWNlSG9sZGVyc0xlbiA+IDBcbiAgICA/IHZhbGlkTGVuIC0gNFxuICAgIDogdmFsaWRMZW5cblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSArPSA0KSB7XG4gICAgdG1wID1cbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSldIDw8IDE4KSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPDwgMTIpIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDIpXSA8PCA2KSB8XG4gICAgICByZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDMpXVxuICAgIGFycltjdXJCeXRlKytdID0gKHRtcCA+PiAxNikgJiAweEZGXG4gICAgYXJyW2N1ckJ5dGUrK10gPSAodG1wID4+IDgpICYgMHhGRlxuICAgIGFycltjdXJCeXRlKytdID0gdG1wICYgMHhGRlxuICB9XG5cbiAgaWYgKHBsYWNlSG9sZGVyc0xlbiA9PT0gMikge1xuICAgIHRtcCA9XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkpXSA8PCAyKSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAxKV0gPj4gNClcbiAgICBhcnJbY3VyQnl0ZSsrXSA9IHRtcCAmIDB4RkZcbiAgfVxuXG4gIGlmIChwbGFjZUhvbGRlcnNMZW4gPT09IDEpIHtcbiAgICB0bXAgPVxuICAgICAgKHJldkxvb2t1cFtiNjQuY2hhckNvZGVBdChpKV0gPDwgMTApIHxcbiAgICAgIChyZXZMb29rdXBbYjY0LmNoYXJDb2RlQXQoaSArIDEpXSA8PCA0KSB8XG4gICAgICAocmV2TG9va3VwW2I2NC5jaGFyQ29kZUF0KGkgKyAyKV0gPj4gMilcbiAgICBhcnJbY3VyQnl0ZSsrXSA9ICh0bXAgPj4gOCkgJiAweEZGXG4gICAgYXJyW2N1ckJ5dGUrK10gPSB0bXAgJiAweEZGXG4gIH1cblxuICByZXR1cm4gYXJyXG59XG5cbmZ1bmN0aW9uIHRyaXBsZXRUb0Jhc2U2NCAobnVtKSB7XG4gIHJldHVybiBsb29rdXBbbnVtID4+IDE4ICYgMHgzRl0gK1xuICAgIGxvb2t1cFtudW0gPj4gMTIgJiAweDNGXSArXG4gICAgbG9va3VwW251bSA+PiA2ICYgMHgzRl0gK1xuICAgIGxvb2t1cFtudW0gJiAweDNGXVxufVxuXG5mdW5jdGlvbiBlbmNvZGVDaHVuayAodWludDgsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHRtcFxuICB2YXIgb3V0cHV0ID0gW11cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyBpICs9IDMpIHtcbiAgICB0bXAgPVxuICAgICAgKCh1aW50OFtpXSA8PCAxNikgJiAweEZGMDAwMCkgK1xuICAgICAgKCh1aW50OFtpICsgMV0gPDwgOCkgJiAweEZGMDApICtcbiAgICAgICh1aW50OFtpICsgMl0gJiAweEZGKVxuICAgIG91dHB1dC5wdXNoKHRyaXBsZXRUb0Jhc2U2NCh0bXApKVxuICB9XG4gIHJldHVybiBvdXRwdXQuam9pbignJylcbn1cblxuZnVuY3Rpb24gZnJvbUJ5dGVBcnJheSAodWludDgpIHtcbiAgdmFyIHRtcFxuICB2YXIgbGVuID0gdWludDgubGVuZ3RoXG4gIHZhciBleHRyYUJ5dGVzID0gbGVuICUgMyAvLyBpZiB3ZSBoYXZlIDEgYnl0ZSBsZWZ0LCBwYWQgMiBieXRlc1xuICB2YXIgcGFydHMgPSBbXVxuICB2YXIgbWF4Q2h1bmtMZW5ndGggPSAxNjM4MyAvLyBtdXN0IGJlIG11bHRpcGxlIG9mIDNcblxuICAvLyBnbyB0aHJvdWdoIHRoZSBhcnJheSBldmVyeSB0aHJlZSBieXRlcywgd2UnbGwgZGVhbCB3aXRoIHRyYWlsaW5nIHN0dWZmIGxhdGVyXG4gIGZvciAodmFyIGkgPSAwLCBsZW4yID0gbGVuIC0gZXh0cmFCeXRlczsgaSA8IGxlbjI7IGkgKz0gbWF4Q2h1bmtMZW5ndGgpIHtcbiAgICBwYXJ0cy5wdXNoKGVuY29kZUNodW5rKFxuICAgICAgdWludDgsIGksIChpICsgbWF4Q2h1bmtMZW5ndGgpID4gbGVuMiA/IGxlbjIgOiAoaSArIG1heENodW5rTGVuZ3RoKVxuICAgICkpXG4gIH1cblxuICAvLyBwYWQgdGhlIGVuZCB3aXRoIHplcm9zLCBidXQgbWFrZSBzdXJlIHRvIG5vdCBmb3JnZXQgdGhlIGV4dHJhIGJ5dGVzXG4gIGlmIChleHRyYUJ5dGVzID09PSAxKSB7XG4gICAgdG1wID0gdWludDhbbGVuIC0gMV1cbiAgICBwYXJ0cy5wdXNoKFxuICAgICAgbG9va3VwW3RtcCA+PiAyXSArXG4gICAgICBsb29rdXBbKHRtcCA8PCA0KSAmIDB4M0ZdICtcbiAgICAgICc9PSdcbiAgICApXG4gIH0gZWxzZSBpZiAoZXh0cmFCeXRlcyA9PT0gMikge1xuICAgIHRtcCA9ICh1aW50OFtsZW4gLSAyXSA8PCA4KSArIHVpbnQ4W2xlbiAtIDFdXG4gICAgcGFydHMucHVzaChcbiAgICAgIGxvb2t1cFt0bXAgPj4gMTBdICtcbiAgICAgIGxvb2t1cFsodG1wID4+IDQpICYgMHgzRl0gK1xuICAgICAgbG9va3VwWyh0bXAgPDwgMikgJiAweDNGXSArXG4gICAgICAnPSdcbiAgICApXG4gIH1cblxuICByZXR1cm4gcGFydHMuam9pbignJylcbn1cbiIsIi8vIChwdWJsaWMpIENvbnN0cnVjdG9yXG5mdW5jdGlvbiBCaWdJbnRlZ2VyKGEsIGIsIGMpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIEJpZ0ludGVnZXIpKVxuICAgIHJldHVybiBuZXcgQmlnSW50ZWdlcihhLCBiLCBjKVxuXG4gIGlmIChhICE9IG51bGwpIHtcbiAgICBpZiAoXCJudW1iZXJcIiA9PSB0eXBlb2YgYSkgdGhpcy5mcm9tTnVtYmVyKGEsIGIsIGMpXG4gICAgZWxzZSBpZiAoYiA9PSBudWxsICYmIFwic3RyaW5nXCIgIT0gdHlwZW9mIGEpIHRoaXMuZnJvbVN0cmluZyhhLCAyNTYpXG4gICAgZWxzZSB0aGlzLmZyb21TdHJpbmcoYSwgYilcbiAgfVxufVxuXG52YXIgcHJvdG8gPSBCaWdJbnRlZ2VyLnByb3RvdHlwZVxuXG4vLyBkdWNrLXR5cGVkIGlzQmlnSW50ZWdlclxucHJvdG8uX19iaWdpID0gcmVxdWlyZSgnLi4vcGFja2FnZS5qc29uJykudmVyc2lvblxuQmlnSW50ZWdlci5pc0JpZ0ludGVnZXIgPSBmdW5jdGlvbiAob2JqLCBjaGVja192ZXIpIHtcbiAgcmV0dXJuIG9iaiAmJiBvYmouX19iaWdpICYmICghY2hlY2tfdmVyIHx8IG9iai5fX2JpZ2kgPT09IHByb3RvLl9fYmlnaSlcbn1cblxuLy8gQml0cyBwZXIgZGlnaXRcbnZhciBkYml0c1xuXG4vLyBhbTogQ29tcHV0ZSB3X2ogKz0gKHgqdGhpc19pKSwgcHJvcGFnYXRlIGNhcnJpZXMsXG4vLyBjIGlzIGluaXRpYWwgY2FycnksIHJldHVybnMgZmluYWwgY2FycnkuXG4vLyBjIDwgMypkdmFsdWUsIHggPCAyKmR2YWx1ZSwgdGhpc19pIDwgZHZhbHVlXG4vLyBXZSBuZWVkIHRvIHNlbGVjdCB0aGUgZmFzdGVzdCBvbmUgdGhhdCB3b3JrcyBpbiB0aGlzIGVudmlyb25tZW50LlxuXG4vLyBhbTE6IHVzZSBhIHNpbmdsZSBtdWx0IGFuZCBkaXZpZGUgdG8gZ2V0IHRoZSBoaWdoIGJpdHMsXG4vLyBtYXggZGlnaXQgYml0cyBzaG91bGQgYmUgMjYgYmVjYXVzZVxuLy8gbWF4IGludGVybmFsIHZhbHVlID0gMipkdmFsdWVeMi0yKmR2YWx1ZSAoPCAyXjUzKVxuZnVuY3Rpb24gYW0xKGksIHgsIHcsIGosIGMsIG4pIHtcbiAgd2hpbGUgKC0tbiA+PSAwKSB7XG4gICAgdmFyIHYgPSB4ICogdGhpc1tpKytdICsgd1tqXSArIGNcbiAgICBjID0gTWF0aC5mbG9vcih2IC8gMHg0MDAwMDAwKVxuICAgIHdbaisrXSA9IHYgJiAweDNmZmZmZmZcbiAgfVxuICByZXR1cm4gY1xufVxuLy8gYW0yIGF2b2lkcyBhIGJpZyBtdWx0LWFuZC1leHRyYWN0IGNvbXBsZXRlbHkuXG4vLyBNYXggZGlnaXQgYml0cyBzaG91bGQgYmUgPD0gMzAgYmVjYXVzZSB3ZSBkbyBiaXR3aXNlIG9wc1xuLy8gb24gdmFsdWVzIHVwIHRvIDIqaGR2YWx1ZV4yLWhkdmFsdWUtMSAoPCAyXjMxKVxuZnVuY3Rpb24gYW0yKGksIHgsIHcsIGosIGMsIG4pIHtcbiAgdmFyIHhsID0geCAmIDB4N2ZmZixcbiAgICB4aCA9IHggPj4gMTVcbiAgd2hpbGUgKC0tbiA+PSAwKSB7XG4gICAgdmFyIGwgPSB0aGlzW2ldICYgMHg3ZmZmXG4gICAgdmFyIGggPSB0aGlzW2krK10gPj4gMTVcbiAgICB2YXIgbSA9IHhoICogbCArIGggKiB4bFxuICAgIGwgPSB4bCAqIGwgKyAoKG0gJiAweDdmZmYpIDw8IDE1KSArIHdbal0gKyAoYyAmIDB4M2ZmZmZmZmYpXG4gICAgYyA9IChsID4+PiAzMCkgKyAobSA+Pj4gMTUpICsgeGggKiBoICsgKGMgPj4+IDMwKVxuICAgIHdbaisrXSA9IGwgJiAweDNmZmZmZmZmXG4gIH1cbiAgcmV0dXJuIGNcbn1cbi8vIEFsdGVybmF0ZWx5LCBzZXQgbWF4IGRpZ2l0IGJpdHMgdG8gMjggc2luY2Ugc29tZVxuLy8gYnJvd3NlcnMgc2xvdyBkb3duIHdoZW4gZGVhbGluZyB3aXRoIDMyLWJpdCBudW1iZXJzLlxuZnVuY3Rpb24gYW0zKGksIHgsIHcsIGosIGMsIG4pIHtcbiAgdmFyIHhsID0geCAmIDB4M2ZmZixcbiAgICB4aCA9IHggPj4gMTRcbiAgd2hpbGUgKC0tbiA+PSAwKSB7XG4gICAgdmFyIGwgPSB0aGlzW2ldICYgMHgzZmZmXG4gICAgdmFyIGggPSB0aGlzW2krK10gPj4gMTRcbiAgICB2YXIgbSA9IHhoICogbCArIGggKiB4bFxuICAgIGwgPSB4bCAqIGwgKyAoKG0gJiAweDNmZmYpIDw8IDE0KSArIHdbal0gKyBjXG4gICAgYyA9IChsID4+IDI4KSArIChtID4+IDE0KSArIHhoICogaFxuICAgIHdbaisrXSA9IGwgJiAweGZmZmZmZmZcbiAgfVxuICByZXR1cm4gY1xufVxuXG4vLyB3dGY/XG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5hbSA9IGFtMVxuZGJpdHMgPSAyNlxuXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5EQiA9IGRiaXRzXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5ETSA9ICgoMSA8PCBkYml0cykgLSAxKVxudmFyIERWID0gQmlnSW50ZWdlci5wcm90b3R5cGUuRFYgPSAoMSA8PCBkYml0cylcblxudmFyIEJJX0ZQID0gNTJcbkJpZ0ludGVnZXIucHJvdG90eXBlLkZWID0gTWF0aC5wb3coMiwgQklfRlApXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS5GMSA9IEJJX0ZQIC0gZGJpdHNcbkJpZ0ludGVnZXIucHJvdG90eXBlLkYyID0gMiAqIGRiaXRzIC0gQklfRlBcblxuLy8gRGlnaXQgY29udmVyc2lvbnNcbnZhciBCSV9STSA9IFwiMDEyMzQ1Njc4OWFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6XCJcbnZhciBCSV9SQyA9IG5ldyBBcnJheSgpXG52YXIgcnIsIHZ2XG5yciA9IFwiMFwiLmNoYXJDb2RlQXQoMClcbmZvciAodnYgPSAwOyB2diA8PSA5OyArK3Z2KSBCSV9SQ1tycisrXSA9IHZ2XG5yciA9IFwiYVwiLmNoYXJDb2RlQXQoMClcbmZvciAodnYgPSAxMDsgdnYgPCAzNjsgKyt2dikgQklfUkNbcnIrK10gPSB2dlxucnIgPSBcIkFcIi5jaGFyQ29kZUF0KDApXG5mb3IgKHZ2ID0gMTA7IHZ2IDwgMzY7ICsrdnYpIEJJX1JDW3JyKytdID0gdnZcblxuZnVuY3Rpb24gaW50MmNoYXIobikge1xuICByZXR1cm4gQklfUk0uY2hhckF0KG4pXG59XG5cbmZ1bmN0aW9uIGludEF0KHMsIGkpIHtcbiAgdmFyIGMgPSBCSV9SQ1tzLmNoYXJDb2RlQXQoaSldXG4gIHJldHVybiAoYyA9PSBudWxsKSA/IC0xIDogY1xufVxuXG4vLyAocHJvdGVjdGVkKSBjb3B5IHRoaXMgdG8gclxuZnVuY3Rpb24gYm5wQ29weVRvKHIpIHtcbiAgZm9yICh2YXIgaSA9IHRoaXMudCAtIDE7IGkgPj0gMDsgLS1pKSByW2ldID0gdGhpc1tpXVxuICByLnQgPSB0aGlzLnRcbiAgci5zID0gdGhpcy5zXG59XG5cbi8vIChwcm90ZWN0ZWQpIHNldCBmcm9tIGludGVnZXIgdmFsdWUgeCwgLURWIDw9IHggPCBEVlxuZnVuY3Rpb24gYm5wRnJvbUludCh4KSB7XG4gIHRoaXMudCA9IDFcbiAgdGhpcy5zID0gKHggPCAwKSA/IC0xIDogMFxuICBpZiAoeCA+IDApIHRoaXNbMF0gPSB4XG4gIGVsc2UgaWYgKHggPCAtMSkgdGhpc1swXSA9IHggKyBEVlxuICBlbHNlIHRoaXMudCA9IDBcbn1cblxuLy8gcmV0dXJuIGJpZ2ludCBpbml0aWFsaXplZCB0byB2YWx1ZVxuZnVuY3Rpb24gbmJ2KGkpIHtcbiAgdmFyIHIgPSBuZXcgQmlnSW50ZWdlcigpXG4gIHIuZnJvbUludChpKVxuICByZXR1cm4gclxufVxuXG4vLyAocHJvdGVjdGVkKSBzZXQgZnJvbSBzdHJpbmcgYW5kIHJhZGl4XG5mdW5jdGlvbiBibnBGcm9tU3RyaW5nKHMsIGIpIHtcbiAgdmFyIHNlbGYgPSB0aGlzXG5cbiAgdmFyIGtcbiAgaWYgKGIgPT0gMTYpIGsgPSA0XG4gIGVsc2UgaWYgKGIgPT0gOCkgayA9IDNcbiAgZWxzZSBpZiAoYiA9PSAyNTYpIGsgPSA4OyAvLyBieXRlIGFycmF5XG4gIGVsc2UgaWYgKGIgPT0gMikgayA9IDFcbiAgZWxzZSBpZiAoYiA9PSAzMikgayA9IDVcbiAgZWxzZSBpZiAoYiA9PSA0KSBrID0gMlxuICBlbHNlIHtcbiAgICBzZWxmLmZyb21SYWRpeChzLCBiKVxuICAgIHJldHVyblxuICB9XG4gIHNlbGYudCA9IDBcbiAgc2VsZi5zID0gMFxuICB2YXIgaSA9IHMubGVuZ3RoLFxuICAgIG1pID0gZmFsc2UsXG4gICAgc2ggPSAwXG4gIHdoaWxlICgtLWkgPj0gMCkge1xuICAgIHZhciB4ID0gKGsgPT0gOCkgPyBzW2ldICYgMHhmZiA6IGludEF0KHMsIGkpXG4gICAgaWYgKHggPCAwKSB7XG4gICAgICBpZiAocy5jaGFyQXQoaSkgPT0gXCItXCIpIG1pID0gdHJ1ZVxuICAgICAgY29udGludWVcbiAgICB9XG4gICAgbWkgPSBmYWxzZVxuICAgIGlmIChzaCA9PSAwKVxuICAgICAgc2VsZltzZWxmLnQrK10gPSB4XG4gICAgZWxzZSBpZiAoc2ggKyBrID4gc2VsZi5EQikge1xuICAgICAgc2VsZltzZWxmLnQgLSAxXSB8PSAoeCAmICgoMSA8PCAoc2VsZi5EQiAtIHNoKSkgLSAxKSkgPDwgc2hcbiAgICAgIHNlbGZbc2VsZi50KytdID0gKHggPj4gKHNlbGYuREIgLSBzaCkpXG4gICAgfSBlbHNlXG4gICAgICBzZWxmW3NlbGYudCAtIDFdIHw9IHggPDwgc2hcbiAgICBzaCArPSBrXG4gICAgaWYgKHNoID49IHNlbGYuREIpIHNoIC09IHNlbGYuREJcbiAgfVxuICBpZiAoayA9PSA4ICYmIChzWzBdICYgMHg4MCkgIT0gMCkge1xuICAgIHNlbGYucyA9IC0xXG4gICAgaWYgKHNoID4gMCkgc2VsZltzZWxmLnQgLSAxXSB8PSAoKDEgPDwgKHNlbGYuREIgLSBzaCkpIC0gMSkgPDwgc2hcbiAgfVxuICBzZWxmLmNsYW1wKClcbiAgaWYgKG1pKSBCaWdJbnRlZ2VyLlpFUk8uc3ViVG8oc2VsZiwgc2VsZilcbn1cblxuLy8gKHByb3RlY3RlZCkgY2xhbXAgb2ZmIGV4Y2VzcyBoaWdoIHdvcmRzXG5mdW5jdGlvbiBibnBDbGFtcCgpIHtcbiAgdmFyIGMgPSB0aGlzLnMgJiB0aGlzLkRNXG4gIHdoaWxlICh0aGlzLnQgPiAwICYmIHRoaXNbdGhpcy50IC0gMV0gPT0gYyktLXRoaXMudFxufVxuXG4vLyAocHVibGljKSByZXR1cm4gc3RyaW5nIHJlcHJlc2VudGF0aW9uIGluIGdpdmVuIHJhZGl4XG5mdW5jdGlvbiBiblRvU3RyaW5nKGIpIHtcbiAgdmFyIHNlbGYgPSB0aGlzXG4gIGlmIChzZWxmLnMgPCAwKSByZXR1cm4gXCItXCIgKyBzZWxmLm5lZ2F0ZSgpXG4gICAgLnRvU3RyaW5nKGIpXG4gIHZhciBrXG4gIGlmIChiID09IDE2KSBrID0gNFxuICBlbHNlIGlmIChiID09IDgpIGsgPSAzXG4gIGVsc2UgaWYgKGIgPT0gMikgayA9IDFcbiAgZWxzZSBpZiAoYiA9PSAzMikgayA9IDVcbiAgZWxzZSBpZiAoYiA9PSA0KSBrID0gMlxuICBlbHNlIHJldHVybiBzZWxmLnRvUmFkaXgoYilcbiAgdmFyIGttID0gKDEgPDwgaykgLSAxLFxuICAgIGQsIG0gPSBmYWxzZSxcbiAgICByID0gXCJcIixcbiAgICBpID0gc2VsZi50XG4gIHZhciBwID0gc2VsZi5EQiAtIChpICogc2VsZi5EQikgJSBrXG4gIGlmIChpLS0gPiAwKSB7XG4gICAgaWYgKHAgPCBzZWxmLkRCICYmIChkID0gc2VsZltpXSA+PiBwKSA+IDApIHtcbiAgICAgIG0gPSB0cnVlXG4gICAgICByID0gaW50MmNoYXIoZClcbiAgICB9XG4gICAgd2hpbGUgKGkgPj0gMCkge1xuICAgICAgaWYgKHAgPCBrKSB7XG4gICAgICAgIGQgPSAoc2VsZltpXSAmICgoMSA8PCBwKSAtIDEpKSA8PCAoayAtIHApXG4gICAgICAgIGQgfD0gc2VsZlstLWldID4+IChwICs9IHNlbGYuREIgLSBrKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZCA9IChzZWxmW2ldID4+IChwIC09IGspKSAmIGttXG4gICAgICAgIGlmIChwIDw9IDApIHtcbiAgICAgICAgICBwICs9IHNlbGYuREJcbiAgICAgICAgICAtLWlcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGQgPiAwKSBtID0gdHJ1ZVxuICAgICAgaWYgKG0pIHIgKz0gaW50MmNoYXIoZClcbiAgICB9XG4gIH1cbiAgcmV0dXJuIG0gPyByIDogXCIwXCJcbn1cblxuLy8gKHB1YmxpYykgLXRoaXNcbmZ1bmN0aW9uIGJuTmVnYXRlKCkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHRoaXMsIHIpXG4gIHJldHVybiByXG59XG5cbi8vIChwdWJsaWMpIHx0aGlzfFxuZnVuY3Rpb24gYm5BYnMoKSB7XG4gIHJldHVybiAodGhpcy5zIDwgMCkgPyB0aGlzLm5lZ2F0ZSgpIDogdGhpc1xufVxuXG4vLyAocHVibGljKSByZXR1cm4gKyBpZiB0aGlzID4gYSwgLSBpZiB0aGlzIDwgYSwgMCBpZiBlcXVhbFxuZnVuY3Rpb24gYm5Db21wYXJlVG8oYSkge1xuICB2YXIgciA9IHRoaXMucyAtIGEuc1xuICBpZiAociAhPSAwKSByZXR1cm4gclxuICB2YXIgaSA9IHRoaXMudFxuICByID0gaSAtIGEudFxuICBpZiAociAhPSAwKSByZXR1cm4gKHRoaXMucyA8IDApID8gLXIgOiByXG4gIHdoaWxlICgtLWkgPj0gMClcbiAgICBpZiAoKHIgPSB0aGlzW2ldIC0gYVtpXSkgIT0gMCkgcmV0dXJuIHJcbiAgcmV0dXJuIDBcbn1cblxuLy8gcmV0dXJucyBiaXQgbGVuZ3RoIG9mIHRoZSBpbnRlZ2VyIHhcbmZ1bmN0aW9uIG5iaXRzKHgpIHtcbiAgdmFyIHIgPSAxLFxuICAgIHRcbiAgaWYgKCh0ID0geCA+Pj4gMTYpICE9IDApIHtcbiAgICB4ID0gdFxuICAgIHIgKz0gMTZcbiAgfVxuICBpZiAoKHQgPSB4ID4+IDgpICE9IDApIHtcbiAgICB4ID0gdFxuICAgIHIgKz0gOFxuICB9XG4gIGlmICgodCA9IHggPj4gNCkgIT0gMCkge1xuICAgIHggPSB0XG4gICAgciArPSA0XG4gIH1cbiAgaWYgKCh0ID0geCA+PiAyKSAhPSAwKSB7XG4gICAgeCA9IHRcbiAgICByICs9IDJcbiAgfVxuICBpZiAoKHQgPSB4ID4+IDEpICE9IDApIHtcbiAgICB4ID0gdFxuICAgIHIgKz0gMVxuICB9XG4gIHJldHVybiByXG59XG5cbi8vIChwdWJsaWMpIHJldHVybiB0aGUgbnVtYmVyIG9mIGJpdHMgaW4gXCJ0aGlzXCJcbmZ1bmN0aW9uIGJuQml0TGVuZ3RoKCkge1xuICBpZiAodGhpcy50IDw9IDApIHJldHVybiAwXG4gIHJldHVybiB0aGlzLkRCICogKHRoaXMudCAtIDEpICsgbmJpdHModGhpc1t0aGlzLnQgLSAxXSBeICh0aGlzLnMgJiB0aGlzLkRNKSlcbn1cblxuLy8gKHB1YmxpYykgcmV0dXJuIHRoZSBudW1iZXIgb2YgYnl0ZXMgaW4gXCJ0aGlzXCJcbmZ1bmN0aW9uIGJuQnl0ZUxlbmd0aCgpIHtcbiAgcmV0dXJuIHRoaXMuYml0TGVuZ3RoKCkgPj4gM1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyA8PCBuKkRCXG5mdW5jdGlvbiBibnBETFNoaWZ0VG8obiwgcikge1xuICB2YXIgaVxuICBmb3IgKGkgPSB0aGlzLnQgLSAxOyBpID49IDA7IC0taSkgcltpICsgbl0gPSB0aGlzW2ldXG4gIGZvciAoaSA9IG4gLSAxOyBpID49IDA7IC0taSkgcltpXSA9IDBcbiAgci50ID0gdGhpcy50ICsgblxuICByLnMgPSB0aGlzLnNcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IHRoaXMgPj4gbipEQlxuZnVuY3Rpb24gYm5wRFJTaGlmdFRvKG4sIHIpIHtcbiAgZm9yICh2YXIgaSA9IG47IGkgPCB0aGlzLnQ7ICsraSkgcltpIC0gbl0gPSB0aGlzW2ldXG4gIHIudCA9IE1hdGgubWF4KHRoaXMudCAtIG4sIDApXG4gIHIucyA9IHRoaXMuc1xufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyA8PCBuXG5mdW5jdGlvbiBibnBMU2hpZnRUbyhuLCByKSB7XG4gIHZhciBzZWxmID0gdGhpc1xuICB2YXIgYnMgPSBuICUgc2VsZi5EQlxuICB2YXIgY2JzID0gc2VsZi5EQiAtIGJzXG4gIHZhciBibSA9ICgxIDw8IGNicykgLSAxXG4gIHZhciBkcyA9IE1hdGguZmxvb3IobiAvIHNlbGYuREIpLFxuICAgIGMgPSAoc2VsZi5zIDw8IGJzKSAmIHNlbGYuRE0sXG4gICAgaVxuICBmb3IgKGkgPSBzZWxmLnQgLSAxOyBpID49IDA7IC0taSkge1xuICAgIHJbaSArIGRzICsgMV0gPSAoc2VsZltpXSA+PiBjYnMpIHwgY1xuICAgIGMgPSAoc2VsZltpXSAmIGJtKSA8PCBic1xuICB9XG4gIGZvciAoaSA9IGRzIC0gMTsgaSA+PSAwOyAtLWkpIHJbaV0gPSAwXG4gIHJbZHNdID0gY1xuICByLnQgPSBzZWxmLnQgKyBkcyArIDFcbiAgci5zID0gc2VsZi5zXG4gIHIuY2xhbXAoKVxufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyA+PiBuXG5mdW5jdGlvbiBibnBSU2hpZnRUbyhuLCByKSB7XG4gIHZhciBzZWxmID0gdGhpc1xuICByLnMgPSBzZWxmLnNcbiAgdmFyIGRzID0gTWF0aC5mbG9vcihuIC8gc2VsZi5EQilcbiAgaWYgKGRzID49IHNlbGYudCkge1xuICAgIHIudCA9IDBcbiAgICByZXR1cm5cbiAgfVxuICB2YXIgYnMgPSBuICUgc2VsZi5EQlxuICB2YXIgY2JzID0gc2VsZi5EQiAtIGJzXG4gIHZhciBibSA9ICgxIDw8IGJzKSAtIDFcbiAgclswXSA9IHNlbGZbZHNdID4+IGJzXG4gIGZvciAodmFyIGkgPSBkcyArIDE7IGkgPCBzZWxmLnQ7ICsraSkge1xuICAgIHJbaSAtIGRzIC0gMV0gfD0gKHNlbGZbaV0gJiBibSkgPDwgY2JzXG4gICAgcltpIC0gZHNdID0gc2VsZltpXSA+PiBic1xuICB9XG4gIGlmIChicyA+IDApIHJbc2VsZi50IC0gZHMgLSAxXSB8PSAoc2VsZi5zICYgYm0pIDw8IGNic1xuICByLnQgPSBzZWxmLnQgLSBkc1xuICByLmNsYW1wKClcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IHRoaXMgLSBhXG5mdW5jdGlvbiBibnBTdWJUbyhhLCByKSB7XG4gIHZhciBzZWxmID0gdGhpc1xuICB2YXIgaSA9IDAsXG4gICAgYyA9IDAsXG4gICAgbSA9IE1hdGgubWluKGEudCwgc2VsZi50KVxuICB3aGlsZSAoaSA8IG0pIHtcbiAgICBjICs9IHNlbGZbaV0gLSBhW2ldXG4gICAgcltpKytdID0gYyAmIHNlbGYuRE1cbiAgICBjID4+PSBzZWxmLkRCXG4gIH1cbiAgaWYgKGEudCA8IHNlbGYudCkge1xuICAgIGMgLT0gYS5zXG4gICAgd2hpbGUgKGkgPCBzZWxmLnQpIHtcbiAgICAgIGMgKz0gc2VsZltpXVxuICAgICAgcltpKytdID0gYyAmIHNlbGYuRE1cbiAgICAgIGMgPj49IHNlbGYuREJcbiAgICB9XG4gICAgYyArPSBzZWxmLnNcbiAgfSBlbHNlIHtcbiAgICBjICs9IHNlbGYuc1xuICAgIHdoaWxlIChpIDwgYS50KSB7XG4gICAgICBjIC09IGFbaV1cbiAgICAgIHJbaSsrXSA9IGMgJiBzZWxmLkRNXG4gICAgICBjID4+PSBzZWxmLkRCXG4gICAgfVxuICAgIGMgLT0gYS5zXG4gIH1cbiAgci5zID0gKGMgPCAwKSA/IC0xIDogMFxuICBpZiAoYyA8IC0xKSByW2krK10gPSBzZWxmLkRWICsgY1xuICBlbHNlIGlmIChjID4gMCkgcltpKytdID0gY1xuICByLnQgPSBpXG4gIHIuY2xhbXAoKVxufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyAqIGEsIHIgIT0gdGhpcyxhIChIQUMgMTQuMTIpXG4vLyBcInRoaXNcIiBzaG91bGQgYmUgdGhlIGxhcmdlciBvbmUgaWYgYXBwcm9wcmlhdGUuXG5mdW5jdGlvbiBibnBNdWx0aXBseVRvKGEsIHIpIHtcbiAgdmFyIHggPSB0aGlzLmFicygpLFxuICAgIHkgPSBhLmFicygpXG4gIHZhciBpID0geC50XG4gIHIudCA9IGkgKyB5LnRcbiAgd2hpbGUgKC0taSA+PSAwKSByW2ldID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgeS50OyArK2kpIHJbaSArIHgudF0gPSB4LmFtKDAsIHlbaV0sIHIsIGksIDAsIHgudClcbiAgci5zID0gMFxuICByLmNsYW1wKClcbiAgaWYgKHRoaXMucyAhPSBhLnMpIEJpZ0ludGVnZXIuWkVSTy5zdWJUbyhyLCByKVxufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpc14yLCByICE9IHRoaXMgKEhBQyAxNC4xNilcbmZ1bmN0aW9uIGJucFNxdWFyZVRvKHIpIHtcbiAgdmFyIHggPSB0aGlzLmFicygpXG4gIHZhciBpID0gci50ID0gMiAqIHgudFxuICB3aGlsZSAoLS1pID49IDApIHJbaV0gPSAwXG4gIGZvciAoaSA9IDA7IGkgPCB4LnQgLSAxOyArK2kpIHtcbiAgICB2YXIgYyA9IHguYW0oaSwgeFtpXSwgciwgMiAqIGksIDAsIDEpXG4gICAgaWYgKChyW2kgKyB4LnRdICs9IHguYW0oaSArIDEsIDIgKiB4W2ldLCByLCAyICogaSArIDEsIGMsIHgudCAtIGkgLSAxKSkgPj0geC5EVikge1xuICAgICAgcltpICsgeC50XSAtPSB4LkRWXG4gICAgICByW2kgKyB4LnQgKyAxXSA9IDFcbiAgICB9XG4gIH1cbiAgaWYgKHIudCA+IDApIHJbci50IC0gMV0gKz0geC5hbShpLCB4W2ldLCByLCAyICogaSwgMCwgMSlcbiAgci5zID0gMFxuICByLmNsYW1wKClcbn1cblxuLy8gKHByb3RlY3RlZCkgZGl2aWRlIHRoaXMgYnkgbSwgcXVvdGllbnQgYW5kIHJlbWFpbmRlciB0byBxLCByIChIQUMgMTQuMjApXG4vLyByICE9IHEsIHRoaXMgIT0gbS4gIHEgb3IgciBtYXkgYmUgbnVsbC5cbmZ1bmN0aW9uIGJucERpdlJlbVRvKG0sIHEsIHIpIHtcbiAgdmFyIHNlbGYgPSB0aGlzXG4gIHZhciBwbSA9IG0uYWJzKClcbiAgaWYgKHBtLnQgPD0gMCkgcmV0dXJuXG4gIHZhciBwdCA9IHNlbGYuYWJzKClcbiAgaWYgKHB0LnQgPCBwbS50KSB7XG4gICAgaWYgKHEgIT0gbnVsbCkgcS5mcm9tSW50KDApXG4gICAgaWYgKHIgIT0gbnVsbCkgc2VsZi5jb3B5VG8ocilcbiAgICByZXR1cm5cbiAgfVxuICBpZiAociA9PSBudWxsKSByID0gbmV3IEJpZ0ludGVnZXIoKVxuICB2YXIgeSA9IG5ldyBCaWdJbnRlZ2VyKCksXG4gICAgdHMgPSBzZWxmLnMsXG4gICAgbXMgPSBtLnNcbiAgdmFyIG5zaCA9IHNlbGYuREIgLSBuYml0cyhwbVtwbS50IC0gMV0pOyAvLyBub3JtYWxpemUgbW9kdWx1c1xuICBpZiAobnNoID4gMCkge1xuICAgIHBtLmxTaGlmdFRvKG5zaCwgeSlcbiAgICBwdC5sU2hpZnRUbyhuc2gsIHIpXG4gIH0gZWxzZSB7XG4gICAgcG0uY29weVRvKHkpXG4gICAgcHQuY29weVRvKHIpXG4gIH1cbiAgdmFyIHlzID0geS50XG4gIHZhciB5MCA9IHlbeXMgLSAxXVxuICBpZiAoeTAgPT0gMCkgcmV0dXJuXG4gIHZhciB5dCA9IHkwICogKDEgPDwgc2VsZi5GMSkgKyAoKHlzID4gMSkgPyB5W3lzIC0gMl0gPj4gc2VsZi5GMiA6IDApXG4gIHZhciBkMSA9IHNlbGYuRlYgLyB5dCxcbiAgICBkMiA9ICgxIDw8IHNlbGYuRjEpIC8geXQsXG4gICAgZSA9IDEgPDwgc2VsZi5GMlxuICB2YXIgaSA9IHIudCxcbiAgICBqID0gaSAtIHlzLFxuICAgIHQgPSAocSA9PSBudWxsKSA/IG5ldyBCaWdJbnRlZ2VyKCkgOiBxXG4gIHkuZGxTaGlmdFRvKGosIHQpXG4gIGlmIChyLmNvbXBhcmVUbyh0KSA+PSAwKSB7XG4gICAgcltyLnQrK10gPSAxXG4gICAgci5zdWJUbyh0LCByKVxuICB9XG4gIEJpZ0ludGVnZXIuT05FLmRsU2hpZnRUbyh5cywgdClcbiAgdC5zdWJUbyh5LCB5KTsgLy8gXCJuZWdhdGl2ZVwiIHkgc28gd2UgY2FuIHJlcGxhY2Ugc3ViIHdpdGggYW0gbGF0ZXJcbiAgd2hpbGUgKHkudCA8IHlzKSB5W3kudCsrXSA9IDBcbiAgd2hpbGUgKC0taiA+PSAwKSB7XG4gICAgLy8gRXN0aW1hdGUgcXVvdGllbnQgZGlnaXRcbiAgICB2YXIgcWQgPSAoclstLWldID09IHkwKSA/IHNlbGYuRE0gOiBNYXRoLmZsb29yKHJbaV0gKiBkMSArIChyW2kgLSAxXSArIGUpICogZDIpXG4gICAgaWYgKChyW2ldICs9IHkuYW0oMCwgcWQsIHIsIGosIDAsIHlzKSkgPCBxZCkgeyAvLyBUcnkgaXQgb3V0XG4gICAgICB5LmRsU2hpZnRUbyhqLCB0KVxuICAgICAgci5zdWJUbyh0LCByKVxuICAgICAgd2hpbGUgKHJbaV0gPCAtLXFkKSByLnN1YlRvKHQsIHIpXG4gICAgfVxuICB9XG4gIGlmIChxICE9IG51bGwpIHtcbiAgICByLmRyU2hpZnRUbyh5cywgcSlcbiAgICBpZiAodHMgIT0gbXMpIEJpZ0ludGVnZXIuWkVSTy5zdWJUbyhxLCBxKVxuICB9XG4gIHIudCA9IHlzXG4gIHIuY2xhbXAoKVxuICBpZiAobnNoID4gMCkgci5yU2hpZnRUbyhuc2gsIHIpOyAvLyBEZW5vcm1hbGl6ZSByZW1haW5kZXJcbiAgaWYgKHRzIDwgMCkgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHIsIHIpXG59XG5cbi8vIChwdWJsaWMpIHRoaXMgbW9kIGFcbmZ1bmN0aW9uIGJuTW9kKGEpIHtcbiAgdmFyIHIgPSBuZXcgQmlnSW50ZWdlcigpXG4gIHRoaXMuYWJzKClcbiAgICAuZGl2UmVtVG8oYSwgbnVsbCwgcilcbiAgaWYgKHRoaXMucyA8IDAgJiYgci5jb21wYXJlVG8oQmlnSW50ZWdlci5aRVJPKSA+IDApIGEuc3ViVG8ociwgcilcbiAgcmV0dXJuIHJcbn1cblxuLy8gTW9kdWxhciByZWR1Y3Rpb24gdXNpbmcgXCJjbGFzc2ljXCIgYWxnb3JpdGhtXG5mdW5jdGlvbiBDbGFzc2ljKG0pIHtcbiAgdGhpcy5tID0gbVxufVxuXG5mdW5jdGlvbiBjQ29udmVydCh4KSB7XG4gIGlmICh4LnMgPCAwIHx8IHguY29tcGFyZVRvKHRoaXMubSkgPj0gMCkgcmV0dXJuIHgubW9kKHRoaXMubSlcbiAgZWxzZSByZXR1cm4geFxufVxuXG5mdW5jdGlvbiBjUmV2ZXJ0KHgpIHtcbiAgcmV0dXJuIHhcbn1cblxuZnVuY3Rpb24gY1JlZHVjZSh4KSB7XG4gIHguZGl2UmVtVG8odGhpcy5tLCBudWxsLCB4KVxufVxuXG5mdW5jdGlvbiBjTXVsVG8oeCwgeSwgcikge1xuICB4Lm11bHRpcGx5VG8oeSwgcilcbiAgdGhpcy5yZWR1Y2Uocilcbn1cblxuZnVuY3Rpb24gY1NxclRvKHgsIHIpIHtcbiAgeC5zcXVhcmVUbyhyKVxuICB0aGlzLnJlZHVjZShyKVxufVxuXG5DbGFzc2ljLnByb3RvdHlwZS5jb252ZXJ0ID0gY0NvbnZlcnRcbkNsYXNzaWMucHJvdG90eXBlLnJldmVydCA9IGNSZXZlcnRcbkNsYXNzaWMucHJvdG90eXBlLnJlZHVjZSA9IGNSZWR1Y2VcbkNsYXNzaWMucHJvdG90eXBlLm11bFRvID0gY011bFRvXG5DbGFzc2ljLnByb3RvdHlwZS5zcXJUbyA9IGNTcXJUb1xuXG4vLyAocHJvdGVjdGVkKSByZXR1cm4gXCItMS90aGlzICUgMl5EQlwiOyB1c2VmdWwgZm9yIE1vbnQuIHJlZHVjdGlvblxuLy8ganVzdGlmaWNhdGlvbjpcbi8vICAgICAgICAgeHkgPT0gMSAobW9kIG0pXG4vLyAgICAgICAgIHh5ID0gIDEra21cbi8vICAgeHkoMi14eSkgPSAoMStrbSkoMS1rbSlcbi8vIHhbeSgyLXh5KV0gPSAxLWteMm1eMlxuLy8geFt5KDIteHkpXSA9PSAxIChtb2QgbV4yKVxuLy8gaWYgeSBpcyAxL3ggbW9kIG0sIHRoZW4geSgyLXh5KSBpcyAxL3ggbW9kIG1eMlxuLy8gc2hvdWxkIHJlZHVjZSB4IGFuZCB5KDIteHkpIGJ5IG1eMiBhdCBlYWNoIHN0ZXAgdG8ga2VlcCBzaXplIGJvdW5kZWQuXG4vLyBKUyBtdWx0aXBseSBcIm92ZXJmbG93c1wiIGRpZmZlcmVudGx5IGZyb20gQy9DKyssIHNvIGNhcmUgaXMgbmVlZGVkIGhlcmUuXG5mdW5jdGlvbiBibnBJbnZEaWdpdCgpIHtcbiAgaWYgKHRoaXMudCA8IDEpIHJldHVybiAwXG4gIHZhciB4ID0gdGhpc1swXVxuICBpZiAoKHggJiAxKSA9PSAwKSByZXR1cm4gMFxuICB2YXIgeSA9IHggJiAzOyAvLyB5ID09IDEveCBtb2QgMl4yXG4gIHkgPSAoeSAqICgyIC0gKHggJiAweGYpICogeSkpICYgMHhmOyAvLyB5ID09IDEveCBtb2QgMl40XG4gIHkgPSAoeSAqICgyIC0gKHggJiAweGZmKSAqIHkpKSAmIDB4ZmY7IC8vIHkgPT0gMS94IG1vZCAyXjhcbiAgeSA9ICh5ICogKDIgLSAoKCh4ICYgMHhmZmZmKSAqIHkpICYgMHhmZmZmKSkpICYgMHhmZmZmOyAvLyB5ID09IDEveCBtb2QgMl4xNlxuICAvLyBsYXN0IHN0ZXAgLSBjYWxjdWxhdGUgaW52ZXJzZSBtb2QgRFYgZGlyZWN0bHlcbiAgLy8gYXNzdW1lcyAxNiA8IERCIDw9IDMyIGFuZCBhc3N1bWVzIGFiaWxpdHkgdG8gaGFuZGxlIDQ4LWJpdCBpbnRzXG4gIHkgPSAoeSAqICgyIC0geCAqIHkgJSB0aGlzLkRWKSkgJSB0aGlzLkRWOyAvLyB5ID09IDEveCBtb2QgMl5kYml0c1xuICAvLyB3ZSByZWFsbHkgd2FudCB0aGUgbmVnYXRpdmUgaW52ZXJzZSwgYW5kIC1EViA8IHkgPCBEVlxuICByZXR1cm4gKHkgPiAwKSA/IHRoaXMuRFYgLSB5IDogLXlcbn1cblxuLy8gTW9udGdvbWVyeSByZWR1Y3Rpb25cbmZ1bmN0aW9uIE1vbnRnb21lcnkobSkge1xuICB0aGlzLm0gPSBtXG4gIHRoaXMubXAgPSBtLmludkRpZ2l0KClcbiAgdGhpcy5tcGwgPSB0aGlzLm1wICYgMHg3ZmZmXG4gIHRoaXMubXBoID0gdGhpcy5tcCA+PiAxNVxuICB0aGlzLnVtID0gKDEgPDwgKG0uREIgLSAxNSkpIC0gMVxuICB0aGlzLm10MiA9IDIgKiBtLnRcbn1cblxuLy8geFIgbW9kIG1cbmZ1bmN0aW9uIG1vbnRDb252ZXJ0KHgpIHtcbiAgdmFyIHIgPSBuZXcgQmlnSW50ZWdlcigpXG4gIHguYWJzKClcbiAgICAuZGxTaGlmdFRvKHRoaXMubS50LCByKVxuICByLmRpdlJlbVRvKHRoaXMubSwgbnVsbCwgcilcbiAgaWYgKHgucyA8IDAgJiYgci5jb21wYXJlVG8oQmlnSW50ZWdlci5aRVJPKSA+IDApIHRoaXMubS5zdWJUbyhyLCByKVxuICByZXR1cm4gclxufVxuXG4vLyB4L1IgbW9kIG1cbmZ1bmN0aW9uIG1vbnRSZXZlcnQoeCkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgeC5jb3B5VG8ocilcbiAgdGhpcy5yZWR1Y2UocilcbiAgcmV0dXJuIHJcbn1cblxuLy8geCA9IHgvUiBtb2QgbSAoSEFDIDE0LjMyKVxuZnVuY3Rpb24gbW9udFJlZHVjZSh4KSB7XG4gIHdoaWxlICh4LnQgPD0gdGhpcy5tdDIpIC8vIHBhZCB4IHNvIGFtIGhhcyBlbm91Z2ggcm9vbSBsYXRlclxuICAgIHhbeC50KytdID0gMFxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMubS50OyArK2kpIHtcbiAgICAvLyBmYXN0ZXIgd2F5IG9mIGNhbGN1bGF0aW5nIHUwID0geFtpXSptcCBtb2QgRFZcbiAgICB2YXIgaiA9IHhbaV0gJiAweDdmZmZcbiAgICB2YXIgdTAgPSAoaiAqIHRoaXMubXBsICsgKCgoaiAqIHRoaXMubXBoICsgKHhbaV0gPj4gMTUpICogdGhpcy5tcGwpICYgdGhpcy51bSkgPDwgMTUpKSAmIHguRE1cbiAgICAvLyB1c2UgYW0gdG8gY29tYmluZSB0aGUgbXVsdGlwbHktc2hpZnQtYWRkIGludG8gb25lIGNhbGxcbiAgICBqID0gaSArIHRoaXMubS50XG4gICAgeFtqXSArPSB0aGlzLm0uYW0oMCwgdTAsIHgsIGksIDAsIHRoaXMubS50KVxuICAgIC8vIHByb3BhZ2F0ZSBjYXJyeVxuICAgIHdoaWxlICh4W2pdID49IHguRFYpIHtcbiAgICAgIHhbal0gLT0geC5EVlxuICAgICAgeFsrK2pdKytcbiAgICB9XG4gIH1cbiAgeC5jbGFtcCgpXG4gIHguZHJTaGlmdFRvKHRoaXMubS50LCB4KVxuICBpZiAoeC5jb21wYXJlVG8odGhpcy5tKSA+PSAwKSB4LnN1YlRvKHRoaXMubSwgeClcbn1cblxuLy8gciA9IFwieF4yL1IgbW9kIG1cIjsgeCAhPSByXG5mdW5jdGlvbiBtb250U3FyVG8oeCwgcikge1xuICB4LnNxdWFyZVRvKHIpXG4gIHRoaXMucmVkdWNlKHIpXG59XG5cbi8vIHIgPSBcInh5L1IgbW9kIG1cIjsgeCx5ICE9IHJcbmZ1bmN0aW9uIG1vbnRNdWxUbyh4LCB5LCByKSB7XG4gIHgubXVsdGlwbHlUbyh5LCByKVxuICB0aGlzLnJlZHVjZShyKVxufVxuXG5Nb250Z29tZXJ5LnByb3RvdHlwZS5jb252ZXJ0ID0gbW9udENvbnZlcnRcbk1vbnRnb21lcnkucHJvdG90eXBlLnJldmVydCA9IG1vbnRSZXZlcnRcbk1vbnRnb21lcnkucHJvdG90eXBlLnJlZHVjZSA9IG1vbnRSZWR1Y2Vcbk1vbnRnb21lcnkucHJvdG90eXBlLm11bFRvID0gbW9udE11bFRvXG5Nb250Z29tZXJ5LnByb3RvdHlwZS5zcXJUbyA9IG1vbnRTcXJUb1xuXG4vLyAocHJvdGVjdGVkKSB0cnVlIGlmZiB0aGlzIGlzIGV2ZW5cbmZ1bmN0aW9uIGJucElzRXZlbigpIHtcbiAgcmV0dXJuICgodGhpcy50ID4gMCkgPyAodGhpc1swXSAmIDEpIDogdGhpcy5zKSA9PSAwXG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXNeZSwgZSA8IDJeMzIsIGRvaW5nIHNxciBhbmQgbXVsIHdpdGggXCJyXCIgKEhBQyAxNC43OSlcbmZ1bmN0aW9uIGJucEV4cChlLCB6KSB7XG4gIGlmIChlID4gMHhmZmZmZmZmZiB8fCBlIDwgMSkgcmV0dXJuIEJpZ0ludGVnZXIuT05FXG4gIHZhciByID0gbmV3IEJpZ0ludGVnZXIoKSxcbiAgICByMiA9IG5ldyBCaWdJbnRlZ2VyKCksXG4gICAgZyA9IHouY29udmVydCh0aGlzKSxcbiAgICBpID0gbmJpdHMoZSkgLSAxXG4gIGcuY29weVRvKHIpXG4gIHdoaWxlICgtLWkgPj0gMCkge1xuICAgIHouc3FyVG8ociwgcjIpXG4gICAgaWYgKChlICYgKDEgPDwgaSkpID4gMCkgei5tdWxUbyhyMiwgZywgcilcbiAgICBlbHNlIHtcbiAgICAgIHZhciB0ID0gclxuICAgICAgciA9IHIyXG4gICAgICByMiA9IHRcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHoucmV2ZXJ0KHIpXG59XG5cbi8vIChwdWJsaWMpIHRoaXNeZSAlIG0sIDAgPD0gZSA8IDJeMzJcbmZ1bmN0aW9uIGJuTW9kUG93SW50KGUsIG0pIHtcbiAgdmFyIHpcbiAgaWYgKGUgPCAyNTYgfHwgbS5pc0V2ZW4oKSkgeiA9IG5ldyBDbGFzc2ljKG0pXG4gIGVsc2UgeiA9IG5ldyBNb250Z29tZXJ5KG0pXG4gIHJldHVybiB0aGlzLmV4cChlLCB6KVxufVxuXG4vLyBwcm90ZWN0ZWRcbnByb3RvLmNvcHlUbyA9IGJucENvcHlUb1xucHJvdG8uZnJvbUludCA9IGJucEZyb21JbnRcbnByb3RvLmZyb21TdHJpbmcgPSBibnBGcm9tU3RyaW5nXG5wcm90by5jbGFtcCA9IGJucENsYW1wXG5wcm90by5kbFNoaWZ0VG8gPSBibnBETFNoaWZ0VG9cbnByb3RvLmRyU2hpZnRUbyA9IGJucERSU2hpZnRUb1xucHJvdG8ubFNoaWZ0VG8gPSBibnBMU2hpZnRUb1xucHJvdG8uclNoaWZ0VG8gPSBibnBSU2hpZnRUb1xucHJvdG8uc3ViVG8gPSBibnBTdWJUb1xucHJvdG8ubXVsdGlwbHlUbyA9IGJucE11bHRpcGx5VG9cbnByb3RvLnNxdWFyZVRvID0gYm5wU3F1YXJlVG9cbnByb3RvLmRpdlJlbVRvID0gYm5wRGl2UmVtVG9cbnByb3RvLmludkRpZ2l0ID0gYm5wSW52RGlnaXRcbnByb3RvLmlzRXZlbiA9IGJucElzRXZlblxucHJvdG8uZXhwID0gYm5wRXhwXG5cbi8vIHB1YmxpY1xucHJvdG8udG9TdHJpbmcgPSBiblRvU3RyaW5nXG5wcm90by5uZWdhdGUgPSBibk5lZ2F0ZVxucHJvdG8uYWJzID0gYm5BYnNcbnByb3RvLmNvbXBhcmVUbyA9IGJuQ29tcGFyZVRvXG5wcm90by5iaXRMZW5ndGggPSBibkJpdExlbmd0aFxucHJvdG8uYnl0ZUxlbmd0aCA9IGJuQnl0ZUxlbmd0aFxucHJvdG8ubW9kID0gYm5Nb2RcbnByb3RvLm1vZFBvd0ludCA9IGJuTW9kUG93SW50XG5cbi8vIChwdWJsaWMpXG5mdW5jdGlvbiBibkNsb25lKCkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgdGhpcy5jb3B5VG8ocilcbiAgcmV0dXJuIHJcbn1cblxuLy8gKHB1YmxpYykgcmV0dXJuIHZhbHVlIGFzIGludGVnZXJcbmZ1bmN0aW9uIGJuSW50VmFsdWUoKSB7XG4gIGlmICh0aGlzLnMgPCAwKSB7XG4gICAgaWYgKHRoaXMudCA9PSAxKSByZXR1cm4gdGhpc1swXSAtIHRoaXMuRFZcbiAgICBlbHNlIGlmICh0aGlzLnQgPT0gMCkgcmV0dXJuIC0xXG4gIH0gZWxzZSBpZiAodGhpcy50ID09IDEpIHJldHVybiB0aGlzWzBdXG4gIGVsc2UgaWYgKHRoaXMudCA9PSAwKSByZXR1cm4gMFxuICAvLyBhc3N1bWVzIDE2IDwgREIgPCAzMlxuICByZXR1cm4gKCh0aGlzWzFdICYgKCgxIDw8ICgzMiAtIHRoaXMuREIpKSAtIDEpKSA8PCB0aGlzLkRCKSB8IHRoaXNbMF1cbn1cblxuLy8gKHB1YmxpYykgcmV0dXJuIHZhbHVlIGFzIGJ5dGVcbmZ1bmN0aW9uIGJuQnl0ZVZhbHVlKCkge1xuICByZXR1cm4gKHRoaXMudCA9PSAwKSA/IHRoaXMucyA6ICh0aGlzWzBdIDw8IDI0KSA+PiAyNFxufVxuXG4vLyAocHVibGljKSByZXR1cm4gdmFsdWUgYXMgc2hvcnQgKGFzc3VtZXMgREI+PTE2KVxuZnVuY3Rpb24gYm5TaG9ydFZhbHVlKCkge1xuICByZXR1cm4gKHRoaXMudCA9PSAwKSA/IHRoaXMucyA6ICh0aGlzWzBdIDw8IDE2KSA+PiAxNlxufVxuXG4vLyAocHJvdGVjdGVkKSByZXR1cm4geCBzLnQuIHJeeCA8IERWXG5mdW5jdGlvbiBibnBDaHVua1NpemUocikge1xuICByZXR1cm4gTWF0aC5mbG9vcihNYXRoLkxOMiAqIHRoaXMuREIgLyBNYXRoLmxvZyhyKSlcbn1cblxuLy8gKHB1YmxpYykgMCBpZiB0aGlzID09IDAsIDEgaWYgdGhpcyA+IDBcbmZ1bmN0aW9uIGJuU2lnTnVtKCkge1xuICBpZiAodGhpcy5zIDwgMCkgcmV0dXJuIC0xXG4gIGVsc2UgaWYgKHRoaXMudCA8PSAwIHx8ICh0aGlzLnQgPT0gMSAmJiB0aGlzWzBdIDw9IDApKSByZXR1cm4gMFxuICBlbHNlIHJldHVybiAxXG59XG5cbi8vIChwcm90ZWN0ZWQpIGNvbnZlcnQgdG8gcmFkaXggc3RyaW5nXG5mdW5jdGlvbiBibnBUb1JhZGl4KGIpIHtcbiAgaWYgKGIgPT0gbnVsbCkgYiA9IDEwXG4gIGlmICh0aGlzLnNpZ251bSgpID09IDAgfHwgYiA8IDIgfHwgYiA+IDM2KSByZXR1cm4gXCIwXCJcbiAgdmFyIGNzID0gdGhpcy5jaHVua1NpemUoYilcbiAgdmFyIGEgPSBNYXRoLnBvdyhiLCBjcylcbiAgdmFyIGQgPSBuYnYoYSksXG4gICAgeSA9IG5ldyBCaWdJbnRlZ2VyKCksXG4gICAgeiA9IG5ldyBCaWdJbnRlZ2VyKCksXG4gICAgciA9IFwiXCJcbiAgdGhpcy5kaXZSZW1UbyhkLCB5LCB6KVxuICB3aGlsZSAoeS5zaWdudW0oKSA+IDApIHtcbiAgICByID0gKGEgKyB6LmludFZhbHVlKCkpXG4gICAgICAudG9TdHJpbmcoYilcbiAgICAgIC5zdWJzdHIoMSkgKyByXG4gICAgeS5kaXZSZW1UbyhkLCB5LCB6KVxuICB9XG4gIHJldHVybiB6LmludFZhbHVlKClcbiAgICAudG9TdHJpbmcoYikgKyByXG59XG5cbi8vIChwcm90ZWN0ZWQpIGNvbnZlcnQgZnJvbSByYWRpeCBzdHJpbmdcbmZ1bmN0aW9uIGJucEZyb21SYWRpeChzLCBiKSB7XG4gIHZhciBzZWxmID0gdGhpc1xuICBzZWxmLmZyb21JbnQoMClcbiAgaWYgKGIgPT0gbnVsbCkgYiA9IDEwXG4gIHZhciBjcyA9IHNlbGYuY2h1bmtTaXplKGIpXG4gIHZhciBkID0gTWF0aC5wb3coYiwgY3MpLFxuICAgIG1pID0gZmFsc2UsXG4gICAgaiA9IDAsXG4gICAgdyA9IDBcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzLmxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHggPSBpbnRBdChzLCBpKVxuICAgIGlmICh4IDwgMCkge1xuICAgICAgaWYgKHMuY2hhckF0KGkpID09IFwiLVwiICYmIHNlbGYuc2lnbnVtKCkgPT0gMCkgbWkgPSB0cnVlXG4gICAgICBjb250aW51ZVxuICAgIH1cbiAgICB3ID0gYiAqIHcgKyB4XG4gICAgaWYgKCsraiA+PSBjcykge1xuICAgICAgc2VsZi5kTXVsdGlwbHkoZClcbiAgICAgIHNlbGYuZEFkZE9mZnNldCh3LCAwKVxuICAgICAgaiA9IDBcbiAgICAgIHcgPSAwXG4gICAgfVxuICB9XG4gIGlmIChqID4gMCkge1xuICAgIHNlbGYuZE11bHRpcGx5KE1hdGgucG93KGIsIGopKVxuICAgIHNlbGYuZEFkZE9mZnNldCh3LCAwKVxuICB9XG4gIGlmIChtaSkgQmlnSW50ZWdlci5aRVJPLnN1YlRvKHNlbGYsIHNlbGYpXG59XG5cbi8vIChwcm90ZWN0ZWQpIGFsdGVybmF0ZSBjb25zdHJ1Y3RvclxuZnVuY3Rpb24gYm5wRnJvbU51bWJlcihhLCBiLCBjKSB7XG4gIHZhciBzZWxmID0gdGhpc1xuICBpZiAoXCJudW1iZXJcIiA9PSB0eXBlb2YgYikge1xuICAgIC8vIG5ldyBCaWdJbnRlZ2VyKGludCxpbnQsUk5HKVxuICAgIGlmIChhIDwgMikgc2VsZi5mcm9tSW50KDEpXG4gICAgZWxzZSB7XG4gICAgICBzZWxmLmZyb21OdW1iZXIoYSwgYylcbiAgICAgIGlmICghc2VsZi50ZXN0Qml0KGEgLSAxKSkgLy8gZm9yY2UgTVNCIHNldFxuICAgICAgICBzZWxmLmJpdHdpc2VUbyhCaWdJbnRlZ2VyLk9ORS5zaGlmdExlZnQoYSAtIDEpLCBvcF9vciwgc2VsZilcbiAgICAgIGlmIChzZWxmLmlzRXZlbigpKSBzZWxmLmRBZGRPZmZzZXQoMSwgMCk7IC8vIGZvcmNlIG9kZFxuICAgICAgd2hpbGUgKCFzZWxmLmlzUHJvYmFibGVQcmltZShiKSkge1xuICAgICAgICBzZWxmLmRBZGRPZmZzZXQoMiwgMClcbiAgICAgICAgaWYgKHNlbGYuYml0TGVuZ3RoKCkgPiBhKSBzZWxmLnN1YlRvKEJpZ0ludGVnZXIuT05FLnNoaWZ0TGVmdChhIC0gMSksIHNlbGYpXG4gICAgICB9XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIC8vIG5ldyBCaWdJbnRlZ2VyKGludCxSTkcpXG4gICAgdmFyIHggPSBuZXcgQXJyYXkoKSxcbiAgICAgIHQgPSBhICYgN1xuICAgIHgubGVuZ3RoID0gKGEgPj4gMykgKyAxXG4gICAgYi5uZXh0Qnl0ZXMoeClcbiAgICBpZiAodCA+IDApIHhbMF0gJj0gKCgxIDw8IHQpIC0gMSlcbiAgICBlbHNlIHhbMF0gPSAwXG4gICAgc2VsZi5mcm9tU3RyaW5nKHgsIDI1NilcbiAgfVxufVxuXG4vLyAocHVibGljKSBjb252ZXJ0IHRvIGJpZ2VuZGlhbiBieXRlIGFycmF5XG5mdW5jdGlvbiBiblRvQnl0ZUFycmF5KCkge1xuICB2YXIgc2VsZiA9IHRoaXNcbiAgdmFyIGkgPSBzZWxmLnQsXG4gICAgciA9IG5ldyBBcnJheSgpXG4gIHJbMF0gPSBzZWxmLnNcbiAgdmFyIHAgPSBzZWxmLkRCIC0gKGkgKiBzZWxmLkRCKSAlIDgsXG4gICAgZCwgayA9IDBcbiAgaWYgKGktLSA+IDApIHtcbiAgICBpZiAocCA8IHNlbGYuREIgJiYgKGQgPSBzZWxmW2ldID4+IHApICE9IChzZWxmLnMgJiBzZWxmLkRNKSA+PiBwKVxuICAgICAgcltrKytdID0gZCB8IChzZWxmLnMgPDwgKHNlbGYuREIgLSBwKSlcbiAgICB3aGlsZSAoaSA+PSAwKSB7XG4gICAgICBpZiAocCA8IDgpIHtcbiAgICAgICAgZCA9IChzZWxmW2ldICYgKCgxIDw8IHApIC0gMSkpIDw8ICg4IC0gcClcbiAgICAgICAgZCB8PSBzZWxmWy0taV0gPj4gKHAgKz0gc2VsZi5EQiAtIDgpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkID0gKHNlbGZbaV0gPj4gKHAgLT0gOCkpICYgMHhmZlxuICAgICAgICBpZiAocCA8PSAwKSB7XG4gICAgICAgICAgcCArPSBzZWxmLkRCXG4gICAgICAgICAgLS1pXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICgoZCAmIDB4ODApICE9IDApIGQgfD0gLTI1NlxuICAgICAgaWYgKGsgPT09IDAgJiYgKHNlbGYucyAmIDB4ODApICE9IChkICYgMHg4MCkpKytrXG4gICAgICBpZiAoayA+IDAgfHwgZCAhPSBzZWxmLnMpIHJbaysrXSA9IGRcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHJcbn1cblxuZnVuY3Rpb24gYm5FcXVhbHMoYSkge1xuICByZXR1cm4gKHRoaXMuY29tcGFyZVRvKGEpID09IDApXG59XG5cbmZ1bmN0aW9uIGJuTWluKGEpIHtcbiAgcmV0dXJuICh0aGlzLmNvbXBhcmVUbyhhKSA8IDApID8gdGhpcyA6IGFcbn1cblxuZnVuY3Rpb24gYm5NYXgoYSkge1xuICByZXR1cm4gKHRoaXMuY29tcGFyZVRvKGEpID4gMCkgPyB0aGlzIDogYVxufVxuXG4vLyAocHJvdGVjdGVkKSByID0gdGhpcyBvcCBhIChiaXR3aXNlKVxuZnVuY3Rpb24gYm5wQml0d2lzZVRvKGEsIG9wLCByKSB7XG4gIHZhciBzZWxmID0gdGhpc1xuICB2YXIgaSwgZiwgbSA9IE1hdGgubWluKGEudCwgc2VsZi50KVxuICBmb3IgKGkgPSAwOyBpIDwgbTsgKytpKSByW2ldID0gb3Aoc2VsZltpXSwgYVtpXSlcbiAgaWYgKGEudCA8IHNlbGYudCkge1xuICAgIGYgPSBhLnMgJiBzZWxmLkRNXG4gICAgZm9yIChpID0gbTsgaSA8IHNlbGYudDsgKytpKSByW2ldID0gb3Aoc2VsZltpXSwgZilcbiAgICByLnQgPSBzZWxmLnRcbiAgfSBlbHNlIHtcbiAgICBmID0gc2VsZi5zICYgc2VsZi5ETVxuICAgIGZvciAoaSA9IG07IGkgPCBhLnQ7ICsraSkgcltpXSA9IG9wKGYsIGFbaV0pXG4gICAgci50ID0gYS50XG4gIH1cbiAgci5zID0gb3Aoc2VsZi5zLCBhLnMpXG4gIHIuY2xhbXAoKVxufVxuXG4vLyAocHVibGljKSB0aGlzICYgYVxuZnVuY3Rpb24gb3BfYW5kKHgsIHkpIHtcbiAgcmV0dXJuIHggJiB5XG59XG5cbmZ1bmN0aW9uIGJuQW5kKGEpIHtcbiAgdmFyIHIgPSBuZXcgQmlnSW50ZWdlcigpXG4gIHRoaXMuYml0d2lzZVRvKGEsIG9wX2FuZCwgcilcbiAgcmV0dXJuIHJcbn1cblxuLy8gKHB1YmxpYykgdGhpcyB8IGFcbmZ1bmN0aW9uIG9wX29yKHgsIHkpIHtcbiAgcmV0dXJuIHggfCB5XG59XG5cbmZ1bmN0aW9uIGJuT3IoYSkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgdGhpcy5iaXR3aXNlVG8oYSwgb3Bfb3IsIHIpXG4gIHJldHVybiByXG59XG5cbi8vIChwdWJsaWMpIHRoaXMgXiBhXG5mdW5jdGlvbiBvcF94b3IoeCwgeSkge1xuICByZXR1cm4geCBeIHlcbn1cblxuZnVuY3Rpb24gYm5Yb3IoYSkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgdGhpcy5iaXR3aXNlVG8oYSwgb3BfeG9yLCByKVxuICByZXR1cm4gclxufVxuXG4vLyAocHVibGljKSB0aGlzICYgfmFcbmZ1bmN0aW9uIG9wX2FuZG5vdCh4LCB5KSB7XG4gIHJldHVybiB4ICYgfnlcbn1cblxuZnVuY3Rpb24gYm5BbmROb3QoYSkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgdGhpcy5iaXR3aXNlVG8oYSwgb3BfYW5kbm90LCByKVxuICByZXR1cm4gclxufVxuXG4vLyAocHVibGljKSB+dGhpc1xuZnVuY3Rpb24gYm5Ob3QoKSB7XG4gIHZhciByID0gbmV3IEJpZ0ludGVnZXIoKVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMudDsgKytpKSByW2ldID0gdGhpcy5ETSAmIH50aGlzW2ldXG4gIHIudCA9IHRoaXMudFxuICByLnMgPSB+dGhpcy5zXG4gIHJldHVybiByXG59XG5cbi8vIChwdWJsaWMpIHRoaXMgPDwgblxuZnVuY3Rpb24gYm5TaGlmdExlZnQobikge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgaWYgKG4gPCAwKSB0aGlzLnJTaGlmdFRvKC1uLCByKVxuICBlbHNlIHRoaXMubFNoaWZ0VG8obiwgcilcbiAgcmV0dXJuIHJcbn1cblxuLy8gKHB1YmxpYykgdGhpcyA+PiBuXG5mdW5jdGlvbiBiblNoaWZ0UmlnaHQobikge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgaWYgKG4gPCAwKSB0aGlzLmxTaGlmdFRvKC1uLCByKVxuICBlbHNlIHRoaXMuclNoaWZ0VG8obiwgcilcbiAgcmV0dXJuIHJcbn1cblxuLy8gcmV0dXJuIGluZGV4IG9mIGxvd2VzdCAxLWJpdCBpbiB4LCB4IDwgMl4zMVxuZnVuY3Rpb24gbGJpdCh4KSB7XG4gIGlmICh4ID09IDApIHJldHVybiAtMVxuICB2YXIgciA9IDBcbiAgaWYgKCh4ICYgMHhmZmZmKSA9PSAwKSB7XG4gICAgeCA+Pj0gMTZcbiAgICByICs9IDE2XG4gIH1cbiAgaWYgKCh4ICYgMHhmZikgPT0gMCkge1xuICAgIHggPj49IDhcbiAgICByICs9IDhcbiAgfVxuICBpZiAoKHggJiAweGYpID09IDApIHtcbiAgICB4ID4+PSA0XG4gICAgciArPSA0XG4gIH1cbiAgaWYgKCh4ICYgMykgPT0gMCkge1xuICAgIHggPj49IDJcbiAgICByICs9IDJcbiAgfVxuICBpZiAoKHggJiAxKSA9PSAwKSsrclxuICByZXR1cm4gclxufVxuXG4vLyAocHVibGljKSByZXR1cm5zIGluZGV4IG9mIGxvd2VzdCAxLWJpdCAob3IgLTEgaWYgbm9uZSlcbmZ1bmN0aW9uIGJuR2V0TG93ZXN0U2V0Qml0KCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMudDsgKytpKVxuICAgIGlmICh0aGlzW2ldICE9IDApIHJldHVybiBpICogdGhpcy5EQiArIGxiaXQodGhpc1tpXSlcbiAgaWYgKHRoaXMucyA8IDApIHJldHVybiB0aGlzLnQgKiB0aGlzLkRCXG4gIHJldHVybiAtMVxufVxuXG4vLyByZXR1cm4gbnVtYmVyIG9mIDEgYml0cyBpbiB4XG5mdW5jdGlvbiBjYml0KHgpIHtcbiAgdmFyIHIgPSAwXG4gIHdoaWxlICh4ICE9IDApIHtcbiAgICB4ICY9IHggLSAxXG4gICAgKytyXG4gIH1cbiAgcmV0dXJuIHJcbn1cblxuLy8gKHB1YmxpYykgcmV0dXJuIG51bWJlciBvZiBzZXQgYml0c1xuZnVuY3Rpb24gYm5CaXRDb3VudCgpIHtcbiAgdmFyIHIgPSAwLFxuICAgIHggPSB0aGlzLnMgJiB0aGlzLkRNXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdGhpcy50OyArK2kpIHIgKz0gY2JpdCh0aGlzW2ldIF4geClcbiAgcmV0dXJuIHJcbn1cblxuLy8gKHB1YmxpYykgdHJ1ZSBpZmYgbnRoIGJpdCBpcyBzZXRcbmZ1bmN0aW9uIGJuVGVzdEJpdChuKSB7XG4gIHZhciBqID0gTWF0aC5mbG9vcihuIC8gdGhpcy5EQilcbiAgaWYgKGogPj0gdGhpcy50KSByZXR1cm4gKHRoaXMucyAhPSAwKVxuICByZXR1cm4gKCh0aGlzW2pdICYgKDEgPDwgKG4gJSB0aGlzLkRCKSkpICE9IDApXG59XG5cbi8vIChwcm90ZWN0ZWQpIHRoaXMgb3AgKDE8PG4pXG5mdW5jdGlvbiBibnBDaGFuZ2VCaXQobiwgb3ApIHtcbiAgdmFyIHIgPSBCaWdJbnRlZ2VyLk9ORS5zaGlmdExlZnQobilcbiAgdGhpcy5iaXR3aXNlVG8ociwgb3AsIHIpXG4gIHJldHVybiByXG59XG5cbi8vIChwdWJsaWMpIHRoaXMgfCAoMTw8bilcbmZ1bmN0aW9uIGJuU2V0Qml0KG4pIHtcbiAgcmV0dXJuIHRoaXMuY2hhbmdlQml0KG4sIG9wX29yKVxufVxuXG4vLyAocHVibGljKSB0aGlzICYgfigxPDxuKVxuZnVuY3Rpb24gYm5DbGVhckJpdChuKSB7XG4gIHJldHVybiB0aGlzLmNoYW5nZUJpdChuLCBvcF9hbmRub3QpXG59XG5cbi8vIChwdWJsaWMpIHRoaXMgXiAoMTw8bilcbmZ1bmN0aW9uIGJuRmxpcEJpdChuKSB7XG4gIHJldHVybiB0aGlzLmNoYW5nZUJpdChuLCBvcF94b3IpXG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSB0aGlzICsgYVxuZnVuY3Rpb24gYm5wQWRkVG8oYSwgcikge1xuICB2YXIgc2VsZiA9IHRoaXNcblxuICB2YXIgaSA9IDAsXG4gICAgYyA9IDAsXG4gICAgbSA9IE1hdGgubWluKGEudCwgc2VsZi50KVxuICB3aGlsZSAoaSA8IG0pIHtcbiAgICBjICs9IHNlbGZbaV0gKyBhW2ldXG4gICAgcltpKytdID0gYyAmIHNlbGYuRE1cbiAgICBjID4+PSBzZWxmLkRCXG4gIH1cbiAgaWYgKGEudCA8IHNlbGYudCkge1xuICAgIGMgKz0gYS5zXG4gICAgd2hpbGUgKGkgPCBzZWxmLnQpIHtcbiAgICAgIGMgKz0gc2VsZltpXVxuICAgICAgcltpKytdID0gYyAmIHNlbGYuRE1cbiAgICAgIGMgPj49IHNlbGYuREJcbiAgICB9XG4gICAgYyArPSBzZWxmLnNcbiAgfSBlbHNlIHtcbiAgICBjICs9IHNlbGYuc1xuICAgIHdoaWxlIChpIDwgYS50KSB7XG4gICAgICBjICs9IGFbaV1cbiAgICAgIHJbaSsrXSA9IGMgJiBzZWxmLkRNXG4gICAgICBjID4+PSBzZWxmLkRCXG4gICAgfVxuICAgIGMgKz0gYS5zXG4gIH1cbiAgci5zID0gKGMgPCAwKSA/IC0xIDogMFxuICBpZiAoYyA+IDApIHJbaSsrXSA9IGNcbiAgZWxzZSBpZiAoYyA8IC0xKSByW2krK10gPSBzZWxmLkRWICsgY1xuICByLnQgPSBpXG4gIHIuY2xhbXAoKVxufVxuXG4vLyAocHVibGljKSB0aGlzICsgYVxuZnVuY3Rpb24gYm5BZGQoYSkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgdGhpcy5hZGRUbyhhLCByKVxuICByZXR1cm4gclxufVxuXG4vLyAocHVibGljKSB0aGlzIC0gYVxuZnVuY3Rpb24gYm5TdWJ0cmFjdChhKSB7XG4gIHZhciByID0gbmV3IEJpZ0ludGVnZXIoKVxuICB0aGlzLnN1YlRvKGEsIHIpXG4gIHJldHVybiByXG59XG5cbi8vIChwdWJsaWMpIHRoaXMgKiBhXG5mdW5jdGlvbiBibk11bHRpcGx5KGEpIHtcbiAgdmFyIHIgPSBuZXcgQmlnSW50ZWdlcigpXG4gIHRoaXMubXVsdGlwbHlUbyhhLCByKVxuICByZXR1cm4gclxufVxuXG4vLyAocHVibGljKSB0aGlzXjJcbmZ1bmN0aW9uIGJuU3F1YXJlKCkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgdGhpcy5zcXVhcmVUbyhyKVxuICByZXR1cm4gclxufVxuXG4vLyAocHVibGljKSB0aGlzIC8gYVxuZnVuY3Rpb24gYm5EaXZpZGUoYSkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgdGhpcy5kaXZSZW1UbyhhLCByLCBudWxsKVxuICByZXR1cm4gclxufVxuXG4vLyAocHVibGljKSB0aGlzICUgYVxuZnVuY3Rpb24gYm5SZW1haW5kZXIoYSkge1xuICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgdGhpcy5kaXZSZW1UbyhhLCBudWxsLCByKVxuICByZXR1cm4gclxufVxuXG4vLyAocHVibGljKSBbdGhpcy9hLHRoaXMlYV1cbmZ1bmN0aW9uIGJuRGl2aWRlQW5kUmVtYWluZGVyKGEpIHtcbiAgdmFyIHEgPSBuZXcgQmlnSW50ZWdlcigpLFxuICAgIHIgPSBuZXcgQmlnSW50ZWdlcigpXG4gIHRoaXMuZGl2UmVtVG8oYSwgcSwgcilcbiAgcmV0dXJuIG5ldyBBcnJheShxLCByKVxufVxuXG4vLyAocHJvdGVjdGVkKSB0aGlzICo9IG4sIHRoaXMgPj0gMCwgMSA8IG4gPCBEVlxuZnVuY3Rpb24gYm5wRE11bHRpcGx5KG4pIHtcbiAgdGhpc1t0aGlzLnRdID0gdGhpcy5hbSgwLCBuIC0gMSwgdGhpcywgMCwgMCwgdGhpcy50KVxuICArK3RoaXMudFxuICB0aGlzLmNsYW1wKClcbn1cblxuLy8gKHByb3RlY3RlZCkgdGhpcyArPSBuIDw8IHcgd29yZHMsIHRoaXMgPj0gMFxuZnVuY3Rpb24gYm5wREFkZE9mZnNldChuLCB3KSB7XG4gIGlmIChuID09IDApIHJldHVyblxuICB3aGlsZSAodGhpcy50IDw9IHcpIHRoaXNbdGhpcy50KytdID0gMFxuICB0aGlzW3ddICs9IG5cbiAgd2hpbGUgKHRoaXNbd10gPj0gdGhpcy5EVikge1xuICAgIHRoaXNbd10gLT0gdGhpcy5EVlxuICAgIGlmICgrK3cgPj0gdGhpcy50KSB0aGlzW3RoaXMudCsrXSA9IDBcbiAgICArK3RoaXNbd11cbiAgfVxufVxuXG4vLyBBIFwibnVsbFwiIHJlZHVjZXJcbmZ1bmN0aW9uIE51bGxFeHAoKSB7fVxuXG5mdW5jdGlvbiBuTm9wKHgpIHtcbiAgcmV0dXJuIHhcbn1cblxuZnVuY3Rpb24gbk11bFRvKHgsIHksIHIpIHtcbiAgeC5tdWx0aXBseVRvKHksIHIpXG59XG5cbmZ1bmN0aW9uIG5TcXJUbyh4LCByKSB7XG4gIHguc3F1YXJlVG8ocilcbn1cblxuTnVsbEV4cC5wcm90b3R5cGUuY29udmVydCA9IG5Ob3Bcbk51bGxFeHAucHJvdG90eXBlLnJldmVydCA9IG5Ob3Bcbk51bGxFeHAucHJvdG90eXBlLm11bFRvID0gbk11bFRvXG5OdWxsRXhwLnByb3RvdHlwZS5zcXJUbyA9IG5TcXJUb1xuXG4vLyAocHVibGljKSB0aGlzXmVcbmZ1bmN0aW9uIGJuUG93KGUpIHtcbiAgcmV0dXJuIHRoaXMuZXhwKGUsIG5ldyBOdWxsRXhwKCkpXG59XG5cbi8vIChwcm90ZWN0ZWQpIHIgPSBsb3dlciBuIHdvcmRzIG9mIFwidGhpcyAqIGFcIiwgYS50IDw9IG5cbi8vIFwidGhpc1wiIHNob3VsZCBiZSB0aGUgbGFyZ2VyIG9uZSBpZiBhcHByb3ByaWF0ZS5cbmZ1bmN0aW9uIGJucE11bHRpcGx5TG93ZXJUbyhhLCBuLCByKSB7XG4gIHZhciBpID0gTWF0aC5taW4odGhpcy50ICsgYS50LCBuKVxuICByLnMgPSAwOyAvLyBhc3N1bWVzIGEsdGhpcyA+PSAwXG4gIHIudCA9IGlcbiAgd2hpbGUgKGkgPiAwKSByWy0taV0gPSAwXG4gIHZhciBqXG4gIGZvciAoaiA9IHIudCAtIHRoaXMudDsgaSA8IGo7ICsraSkgcltpICsgdGhpcy50XSA9IHRoaXMuYW0oMCwgYVtpXSwgciwgaSwgMCwgdGhpcy50KVxuICBmb3IgKGogPSBNYXRoLm1pbihhLnQsIG4pOyBpIDwgajsgKytpKSB0aGlzLmFtKDAsIGFbaV0sIHIsIGksIDAsIG4gLSBpKVxuICByLmNsYW1wKClcbn1cblxuLy8gKHByb3RlY3RlZCkgciA9IFwidGhpcyAqIGFcIiB3aXRob3V0IGxvd2VyIG4gd29yZHMsIG4gPiAwXG4vLyBcInRoaXNcIiBzaG91bGQgYmUgdGhlIGxhcmdlciBvbmUgaWYgYXBwcm9wcmlhdGUuXG5mdW5jdGlvbiBibnBNdWx0aXBseVVwcGVyVG8oYSwgbiwgcikge1xuICAtLW5cbiAgdmFyIGkgPSByLnQgPSB0aGlzLnQgKyBhLnQgLSBuXG4gIHIucyA9IDA7IC8vIGFzc3VtZXMgYSx0aGlzID49IDBcbiAgd2hpbGUgKC0taSA+PSAwKSByW2ldID0gMFxuICBmb3IgKGkgPSBNYXRoLm1heChuIC0gdGhpcy50LCAwKTsgaSA8IGEudDsgKytpKVxuICAgIHJbdGhpcy50ICsgaSAtIG5dID0gdGhpcy5hbShuIC0gaSwgYVtpXSwgciwgMCwgMCwgdGhpcy50ICsgaSAtIG4pXG4gIHIuY2xhbXAoKVxuICByLmRyU2hpZnRUbygxLCByKVxufVxuXG4vLyBCYXJyZXR0IG1vZHVsYXIgcmVkdWN0aW9uXG5mdW5jdGlvbiBCYXJyZXR0KG0pIHtcbiAgLy8gc2V0dXAgQmFycmV0dFxuICB0aGlzLnIyID0gbmV3IEJpZ0ludGVnZXIoKVxuICB0aGlzLnEzID0gbmV3IEJpZ0ludGVnZXIoKVxuICBCaWdJbnRlZ2VyLk9ORS5kbFNoaWZ0VG8oMiAqIG0udCwgdGhpcy5yMilcbiAgdGhpcy5tdSA9IHRoaXMucjIuZGl2aWRlKG0pXG4gIHRoaXMubSA9IG1cbn1cblxuZnVuY3Rpb24gYmFycmV0dENvbnZlcnQoeCkge1xuICBpZiAoeC5zIDwgMCB8fCB4LnQgPiAyICogdGhpcy5tLnQpIHJldHVybiB4Lm1vZCh0aGlzLm0pXG4gIGVsc2UgaWYgKHguY29tcGFyZVRvKHRoaXMubSkgPCAwKSByZXR1cm4geFxuICBlbHNlIHtcbiAgICB2YXIgciA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgICB4LmNvcHlUbyhyKVxuICAgIHRoaXMucmVkdWNlKHIpXG4gICAgcmV0dXJuIHJcbiAgfVxufVxuXG5mdW5jdGlvbiBiYXJyZXR0UmV2ZXJ0KHgpIHtcbiAgcmV0dXJuIHhcbn1cblxuLy8geCA9IHggbW9kIG0gKEhBQyAxNC40MilcbmZ1bmN0aW9uIGJhcnJldHRSZWR1Y2UoeCkge1xuICB2YXIgc2VsZiA9IHRoaXNcbiAgeC5kclNoaWZ0VG8oc2VsZi5tLnQgLSAxLCBzZWxmLnIyKVxuICBpZiAoeC50ID4gc2VsZi5tLnQgKyAxKSB7XG4gICAgeC50ID0gc2VsZi5tLnQgKyAxXG4gICAgeC5jbGFtcCgpXG4gIH1cbiAgc2VsZi5tdS5tdWx0aXBseVVwcGVyVG8oc2VsZi5yMiwgc2VsZi5tLnQgKyAxLCBzZWxmLnEzKVxuICBzZWxmLm0ubXVsdGlwbHlMb3dlclRvKHNlbGYucTMsIHNlbGYubS50ICsgMSwgc2VsZi5yMilcbiAgd2hpbGUgKHguY29tcGFyZVRvKHNlbGYucjIpIDwgMCkgeC5kQWRkT2Zmc2V0KDEsIHNlbGYubS50ICsgMSlcbiAgeC5zdWJUbyhzZWxmLnIyLCB4KVxuICB3aGlsZSAoeC5jb21wYXJlVG8oc2VsZi5tKSA+PSAwKSB4LnN1YlRvKHNlbGYubSwgeClcbn1cblxuLy8gciA9IHheMiBtb2QgbTsgeCAhPSByXG5mdW5jdGlvbiBiYXJyZXR0U3FyVG8oeCwgcikge1xuICB4LnNxdWFyZVRvKHIpXG4gIHRoaXMucmVkdWNlKHIpXG59XG5cbi8vIHIgPSB4KnkgbW9kIG07IHgseSAhPSByXG5mdW5jdGlvbiBiYXJyZXR0TXVsVG8oeCwgeSwgcikge1xuICB4Lm11bHRpcGx5VG8oeSwgcilcbiAgdGhpcy5yZWR1Y2Uocilcbn1cblxuQmFycmV0dC5wcm90b3R5cGUuY29udmVydCA9IGJhcnJldHRDb252ZXJ0XG5CYXJyZXR0LnByb3RvdHlwZS5yZXZlcnQgPSBiYXJyZXR0UmV2ZXJ0XG5CYXJyZXR0LnByb3RvdHlwZS5yZWR1Y2UgPSBiYXJyZXR0UmVkdWNlXG5CYXJyZXR0LnByb3RvdHlwZS5tdWxUbyA9IGJhcnJldHRNdWxUb1xuQmFycmV0dC5wcm90b3R5cGUuc3FyVG8gPSBiYXJyZXR0U3FyVG9cblxuLy8gKHB1YmxpYykgdGhpc15lICUgbSAoSEFDIDE0Ljg1KVxuZnVuY3Rpb24gYm5Nb2RQb3coZSwgbSkge1xuICB2YXIgaSA9IGUuYml0TGVuZ3RoKCksXG4gICAgaywgciA9IG5idigxKSxcbiAgICB6XG4gIGlmIChpIDw9IDApIHJldHVybiByXG4gIGVsc2UgaWYgKGkgPCAxOCkgayA9IDFcbiAgZWxzZSBpZiAoaSA8IDQ4KSBrID0gM1xuICBlbHNlIGlmIChpIDwgMTQ0KSBrID0gNFxuICBlbHNlIGlmIChpIDwgNzY4KSBrID0gNVxuICBlbHNlIGsgPSA2XG4gIGlmIChpIDwgOClcbiAgICB6ID0gbmV3IENsYXNzaWMobSlcbiAgZWxzZSBpZiAobS5pc0V2ZW4oKSlcbiAgICB6ID0gbmV3IEJhcnJldHQobSlcbiAgZWxzZVxuICAgIHogPSBuZXcgTW9udGdvbWVyeShtKVxuXG4gIC8vIHByZWNvbXB1dGF0aW9uXG4gIHZhciBnID0gbmV3IEFycmF5KCksXG4gICAgbiA9IDMsXG4gICAgazEgPSBrIC0gMSxcbiAgICBrbSA9ICgxIDw8IGspIC0gMVxuICBnWzFdID0gei5jb252ZXJ0KHRoaXMpXG4gIGlmIChrID4gMSkge1xuICAgIHZhciBnMiA9IG5ldyBCaWdJbnRlZ2VyKClcbiAgICB6LnNxclRvKGdbMV0sIGcyKVxuICAgIHdoaWxlIChuIDw9IGttKSB7XG4gICAgICBnW25dID0gbmV3IEJpZ0ludGVnZXIoKVxuICAgICAgei5tdWxUbyhnMiwgZ1tuIC0gMl0sIGdbbl0pXG4gICAgICBuICs9IDJcbiAgICB9XG4gIH1cblxuICB2YXIgaiA9IGUudCAtIDEsXG4gICAgdywgaXMxID0gdHJ1ZSxcbiAgICByMiA9IG5ldyBCaWdJbnRlZ2VyKCksXG4gICAgdFxuICBpID0gbmJpdHMoZVtqXSkgLSAxXG4gIHdoaWxlIChqID49IDApIHtcbiAgICBpZiAoaSA+PSBrMSkgdyA9IChlW2pdID4+IChpIC0gazEpKSAmIGttXG4gICAgZWxzZSB7XG4gICAgICB3ID0gKGVbal0gJiAoKDEgPDwgKGkgKyAxKSkgLSAxKSkgPDwgKGsxIC0gaSlcbiAgICAgIGlmIChqID4gMCkgdyB8PSBlW2ogLSAxXSA+PiAodGhpcy5EQiArIGkgLSBrMSlcbiAgICB9XG5cbiAgICBuID0ga1xuICAgIHdoaWxlICgodyAmIDEpID09IDApIHtcbiAgICAgIHcgPj49IDFcbiAgICAgIC0tblxuICAgIH1cbiAgICBpZiAoKGkgLT0gbikgPCAwKSB7XG4gICAgICBpICs9IHRoaXMuREJcbiAgICAgIC0talxuICAgIH1cbiAgICBpZiAoaXMxKSB7IC8vIHJldCA9PSAxLCBkb24ndCBib3RoZXIgc3F1YXJpbmcgb3IgbXVsdGlwbHlpbmcgaXRcbiAgICAgIGdbd10uY29weVRvKHIpXG4gICAgICBpczEgPSBmYWxzZVxuICAgIH0gZWxzZSB7XG4gICAgICB3aGlsZSAobiA+IDEpIHtcbiAgICAgICAgei5zcXJUbyhyLCByMilcbiAgICAgICAgei5zcXJUbyhyMiwgcilcbiAgICAgICAgbiAtPSAyXG4gICAgICB9XG4gICAgICBpZiAobiA+IDApIHouc3FyVG8ociwgcjIpXG4gICAgICBlbHNlIHtcbiAgICAgICAgdCA9IHJcbiAgICAgICAgciA9IHIyXG4gICAgICAgIHIyID0gdFxuICAgICAgfVxuICAgICAgei5tdWxUbyhyMiwgZ1t3XSwgcilcbiAgICB9XG5cbiAgICB3aGlsZSAoaiA+PSAwICYmIChlW2pdICYgKDEgPDwgaSkpID09IDApIHtcbiAgICAgIHouc3FyVG8ociwgcjIpXG4gICAgICB0ID0gclxuICAgICAgciA9IHIyXG4gICAgICByMiA9IHRcbiAgICAgIGlmICgtLWkgPCAwKSB7XG4gICAgICAgIGkgPSB0aGlzLkRCIC0gMVxuICAgICAgICAtLWpcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIHoucmV2ZXJ0KHIpXG59XG5cbi8vIChwdWJsaWMpIGdjZCh0aGlzLGEpIChIQUMgMTQuNTQpXG5mdW5jdGlvbiBibkdDRChhKSB7XG4gIHZhciB4ID0gKHRoaXMucyA8IDApID8gdGhpcy5uZWdhdGUoKSA6IHRoaXMuY2xvbmUoKVxuICB2YXIgeSA9IChhLnMgPCAwKSA/IGEubmVnYXRlKCkgOiBhLmNsb25lKClcbiAgaWYgKHguY29tcGFyZVRvKHkpIDwgMCkge1xuICAgIHZhciB0ID0geFxuICAgIHggPSB5XG4gICAgeSA9IHRcbiAgfVxuICB2YXIgaSA9IHguZ2V0TG93ZXN0U2V0Qml0KCksXG4gICAgZyA9IHkuZ2V0TG93ZXN0U2V0Qml0KClcbiAgaWYgKGcgPCAwKSByZXR1cm4geFxuICBpZiAoaSA8IGcpIGcgPSBpXG4gIGlmIChnID4gMCkge1xuICAgIHguclNoaWZ0VG8oZywgeClcbiAgICB5LnJTaGlmdFRvKGcsIHkpXG4gIH1cbiAgd2hpbGUgKHguc2lnbnVtKCkgPiAwKSB7XG4gICAgaWYgKChpID0geC5nZXRMb3dlc3RTZXRCaXQoKSkgPiAwKSB4LnJTaGlmdFRvKGksIHgpXG4gICAgaWYgKChpID0geS5nZXRMb3dlc3RTZXRCaXQoKSkgPiAwKSB5LnJTaGlmdFRvKGksIHkpXG4gICAgaWYgKHguY29tcGFyZVRvKHkpID49IDApIHtcbiAgICAgIHguc3ViVG8oeSwgeClcbiAgICAgIHguclNoaWZ0VG8oMSwgeClcbiAgICB9IGVsc2Uge1xuICAgICAgeS5zdWJUbyh4LCB5KVxuICAgICAgeS5yU2hpZnRUbygxLCB5KVxuICAgIH1cbiAgfVxuICBpZiAoZyA+IDApIHkubFNoaWZ0VG8oZywgeSlcbiAgcmV0dXJuIHlcbn1cblxuLy8gKHByb3RlY3RlZCkgdGhpcyAlIG4sIG4gPCAyXjI2XG5mdW5jdGlvbiBibnBNb2RJbnQobikge1xuICBpZiAobiA8PSAwKSByZXR1cm4gMFxuICB2YXIgZCA9IHRoaXMuRFYgJSBuLFxuICAgIHIgPSAodGhpcy5zIDwgMCkgPyBuIC0gMSA6IDBcbiAgaWYgKHRoaXMudCA+IDApXG4gICAgaWYgKGQgPT0gMCkgciA9IHRoaXNbMF0gJSBuXG4gICAgZWxzZVxuICAgICAgZm9yICh2YXIgaSA9IHRoaXMudCAtIDE7IGkgPj0gMDsgLS1pKSByID0gKGQgKiByICsgdGhpc1tpXSkgJSBuXG4gIHJldHVybiByXG59XG5cbi8vIChwdWJsaWMpIDEvdGhpcyAlIG0gKEhBQyAxNC42MSlcbmZ1bmN0aW9uIGJuTW9kSW52ZXJzZShtKSB7XG4gIHZhciBhYyA9IG0uaXNFdmVuKClcbiAgaWYgKHRoaXMuc2lnbnVtKCkgPT09IDApIHRocm93IG5ldyBFcnJvcignZGl2aXNpb24gYnkgemVybycpXG4gIGlmICgodGhpcy5pc0V2ZW4oKSAmJiBhYykgfHwgbS5zaWdudW0oKSA9PSAwKSByZXR1cm4gQmlnSW50ZWdlci5aRVJPXG4gIHZhciB1ID0gbS5jbG9uZSgpLFxuICAgIHYgPSB0aGlzLmNsb25lKClcbiAgdmFyIGEgPSBuYnYoMSksXG4gICAgYiA9IG5idigwKSxcbiAgICBjID0gbmJ2KDApLFxuICAgIGQgPSBuYnYoMSlcbiAgd2hpbGUgKHUuc2lnbnVtKCkgIT0gMCkge1xuICAgIHdoaWxlICh1LmlzRXZlbigpKSB7XG4gICAgICB1LnJTaGlmdFRvKDEsIHUpXG4gICAgICBpZiAoYWMpIHtcbiAgICAgICAgaWYgKCFhLmlzRXZlbigpIHx8ICFiLmlzRXZlbigpKSB7XG4gICAgICAgICAgYS5hZGRUbyh0aGlzLCBhKVxuICAgICAgICAgIGIuc3ViVG8obSwgYilcbiAgICAgICAgfVxuICAgICAgICBhLnJTaGlmdFRvKDEsIGEpXG4gICAgICB9IGVsc2UgaWYgKCFiLmlzRXZlbigpKSBiLnN1YlRvKG0sIGIpXG4gICAgICBiLnJTaGlmdFRvKDEsIGIpXG4gICAgfVxuICAgIHdoaWxlICh2LmlzRXZlbigpKSB7XG4gICAgICB2LnJTaGlmdFRvKDEsIHYpXG4gICAgICBpZiAoYWMpIHtcbiAgICAgICAgaWYgKCFjLmlzRXZlbigpIHx8ICFkLmlzRXZlbigpKSB7XG4gICAgICAgICAgYy5hZGRUbyh0aGlzLCBjKVxuICAgICAgICAgIGQuc3ViVG8obSwgZClcbiAgICAgICAgfVxuICAgICAgICBjLnJTaGlmdFRvKDEsIGMpXG4gICAgICB9IGVsc2UgaWYgKCFkLmlzRXZlbigpKSBkLnN1YlRvKG0sIGQpXG4gICAgICBkLnJTaGlmdFRvKDEsIGQpXG4gICAgfVxuICAgIGlmICh1LmNvbXBhcmVUbyh2KSA+PSAwKSB7XG4gICAgICB1LnN1YlRvKHYsIHUpXG4gICAgICBpZiAoYWMpIGEuc3ViVG8oYywgYSlcbiAgICAgIGIuc3ViVG8oZCwgYilcbiAgICB9IGVsc2Uge1xuICAgICAgdi5zdWJUbyh1LCB2KVxuICAgICAgaWYgKGFjKSBjLnN1YlRvKGEsIGMpXG4gICAgICBkLnN1YlRvKGIsIGQpXG4gICAgfVxuICB9XG4gIGlmICh2LmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgIT0gMCkgcmV0dXJuIEJpZ0ludGVnZXIuWkVST1xuICB3aGlsZSAoZC5jb21wYXJlVG8obSkgPj0gMCkgZC5zdWJUbyhtLCBkKVxuICB3aGlsZSAoZC5zaWdudW0oKSA8IDApIGQuYWRkVG8obSwgZClcbiAgcmV0dXJuIGRcbn1cblxudmFyIGxvd3ByaW1lcyA9IFtcbiAgMiwgMywgNSwgNywgMTEsIDEzLCAxNywgMTksIDIzLCAyOSwgMzEsIDM3LCA0MSwgNDMsIDQ3LCA1MywgNTksIDYxLCA2NywgNzEsXG4gIDczLCA3OSwgODMsIDg5LCA5NywgMTAxLCAxMDMsIDEwNywgMTA5LCAxMTMsIDEyNywgMTMxLCAxMzcsIDEzOSwgMTQ5LCAxNTEsXG4gIDE1NywgMTYzLCAxNjcsIDE3MywgMTc5LCAxODEsIDE5MSwgMTkzLCAxOTcsIDE5OSwgMjExLCAyMjMsIDIyNywgMjI5LCAyMzMsXG4gIDIzOSwgMjQxLCAyNTEsIDI1NywgMjYzLCAyNjksIDI3MSwgMjc3LCAyODEsIDI4MywgMjkzLCAzMDcsIDMxMSwgMzEzLCAzMTcsXG4gIDMzMSwgMzM3LCAzNDcsIDM0OSwgMzUzLCAzNTksIDM2NywgMzczLCAzNzksIDM4MywgMzg5LCAzOTcsIDQwMSwgNDA5LCA0MTksXG4gIDQyMSwgNDMxLCA0MzMsIDQzOSwgNDQzLCA0NDksIDQ1NywgNDYxLCA0NjMsIDQ2NywgNDc5LCA0ODcsIDQ5MSwgNDk5LCA1MDMsXG4gIDUwOSwgNTIxLCA1MjMsIDU0MSwgNTQ3LCA1NTcsIDU2MywgNTY5LCA1NzEsIDU3NywgNTg3LCA1OTMsIDU5OSwgNjAxLCA2MDcsXG4gIDYxMywgNjE3LCA2MTksIDYzMSwgNjQxLCA2NDMsIDY0NywgNjUzLCA2NTksIDY2MSwgNjczLCA2NzcsIDY4MywgNjkxLCA3MDEsXG4gIDcwOSwgNzE5LCA3MjcsIDczMywgNzM5LCA3NDMsIDc1MSwgNzU3LCA3NjEsIDc2OSwgNzczLCA3ODcsIDc5NywgODA5LCA4MTEsXG4gIDgyMSwgODIzLCA4MjcsIDgyOSwgODM5LCA4NTMsIDg1NywgODU5LCA4NjMsIDg3NywgODgxLCA4ODMsIDg4NywgOTA3LCA5MTEsXG4gIDkxOSwgOTI5LCA5MzcsIDk0MSwgOTQ3LCA5NTMsIDk2NywgOTcxLCA5NzcsIDk4MywgOTkxLCA5OTdcbl1cblxudmFyIGxwbGltID0gKDEgPDwgMjYpIC8gbG93cHJpbWVzW2xvd3ByaW1lcy5sZW5ndGggLSAxXVxuXG4vLyAocHVibGljKSB0ZXN0IHByaW1hbGl0eSB3aXRoIGNlcnRhaW50eSA+PSAxLS41XnRcbmZ1bmN0aW9uIGJuSXNQcm9iYWJsZVByaW1lKHQpIHtcbiAgdmFyIGksIHggPSB0aGlzLmFicygpXG4gIGlmICh4LnQgPT0gMSAmJiB4WzBdIDw9IGxvd3ByaW1lc1tsb3dwcmltZXMubGVuZ3RoIC0gMV0pIHtcbiAgICBmb3IgKGkgPSAwOyBpIDwgbG93cHJpbWVzLmxlbmd0aDsgKytpKVxuICAgICAgaWYgKHhbMF0gPT0gbG93cHJpbWVzW2ldKSByZXR1cm4gdHJ1ZVxuICAgIHJldHVybiBmYWxzZVxuICB9XG4gIGlmICh4LmlzRXZlbigpKSByZXR1cm4gZmFsc2VcbiAgaSA9IDFcbiAgd2hpbGUgKGkgPCBsb3dwcmltZXMubGVuZ3RoKSB7XG4gICAgdmFyIG0gPSBsb3dwcmltZXNbaV0sXG4gICAgICBqID0gaSArIDFcbiAgICB3aGlsZSAoaiA8IGxvd3ByaW1lcy5sZW5ndGggJiYgbSA8IGxwbGltKSBtICo9IGxvd3ByaW1lc1tqKytdXG4gICAgbSA9IHgubW9kSW50KG0pXG4gICAgd2hpbGUgKGkgPCBqKSBpZiAobSAlIGxvd3ByaW1lc1tpKytdID09IDApIHJldHVybiBmYWxzZVxuICB9XG4gIHJldHVybiB4Lm1pbGxlclJhYmluKHQpXG59XG5cbi8vIChwcm90ZWN0ZWQpIHRydWUgaWYgcHJvYmFibHkgcHJpbWUgKEhBQyA0LjI0LCBNaWxsZXItUmFiaW4pXG5mdW5jdGlvbiBibnBNaWxsZXJSYWJpbih0KSB7XG4gIHZhciBuMSA9IHRoaXMuc3VidHJhY3QoQmlnSW50ZWdlci5PTkUpXG4gIHZhciBrID0gbjEuZ2V0TG93ZXN0U2V0Qml0KClcbiAgaWYgKGsgPD0gMCkgcmV0dXJuIGZhbHNlXG4gIHZhciByID0gbjEuc2hpZnRSaWdodChrKVxuICB0ID0gKHQgKyAxKSA+PiAxXG4gIGlmICh0ID4gbG93cHJpbWVzLmxlbmd0aCkgdCA9IGxvd3ByaW1lcy5sZW5ndGhcbiAgdmFyIGEgPSBuZXcgQmlnSW50ZWdlcihudWxsKVxuICB2YXIgaiwgYmFzZXMgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHQ7ICsraSkge1xuICAgIGZvciAoOzspIHtcbiAgICAgIGogPSBsb3dwcmltZXNbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogbG93cHJpbWVzLmxlbmd0aCldXG4gICAgICBpZiAoYmFzZXMuaW5kZXhPZihqKSA9PSAtMSkgYnJlYWtcbiAgICB9XG4gICAgYmFzZXMucHVzaChqKVxuICAgIGEuZnJvbUludChqKVxuICAgIHZhciB5ID0gYS5tb2RQb3cociwgdGhpcylcbiAgICBpZiAoeS5jb21wYXJlVG8oQmlnSW50ZWdlci5PTkUpICE9IDAgJiYgeS5jb21wYXJlVG8objEpICE9IDApIHtcbiAgICAgIHZhciBqID0gMVxuICAgICAgd2hpbGUgKGorKyA8IGsgJiYgeS5jb21wYXJlVG8objEpICE9IDApIHtcbiAgICAgICAgeSA9IHkubW9kUG93SW50KDIsIHRoaXMpXG4gICAgICAgIGlmICh5LmNvbXBhcmVUbyhCaWdJbnRlZ2VyLk9ORSkgPT0gMCkgcmV0dXJuIGZhbHNlXG4gICAgICB9XG4gICAgICBpZiAoeS5jb21wYXJlVG8objEpICE9IDApIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG4vLyBwcm90ZWN0ZWRcbnByb3RvLmNodW5rU2l6ZSA9IGJucENodW5rU2l6ZVxucHJvdG8udG9SYWRpeCA9IGJucFRvUmFkaXhcbnByb3RvLmZyb21SYWRpeCA9IGJucEZyb21SYWRpeFxucHJvdG8uZnJvbU51bWJlciA9IGJucEZyb21OdW1iZXJcbnByb3RvLmJpdHdpc2VUbyA9IGJucEJpdHdpc2VUb1xucHJvdG8uY2hhbmdlQml0ID0gYm5wQ2hhbmdlQml0XG5wcm90by5hZGRUbyA9IGJucEFkZFRvXG5wcm90by5kTXVsdGlwbHkgPSBibnBETXVsdGlwbHlcbnByb3RvLmRBZGRPZmZzZXQgPSBibnBEQWRkT2Zmc2V0XG5wcm90by5tdWx0aXBseUxvd2VyVG8gPSBibnBNdWx0aXBseUxvd2VyVG9cbnByb3RvLm11bHRpcGx5VXBwZXJUbyA9IGJucE11bHRpcGx5VXBwZXJUb1xucHJvdG8ubW9kSW50ID0gYm5wTW9kSW50XG5wcm90by5taWxsZXJSYWJpbiA9IGJucE1pbGxlclJhYmluXG5cbi8vIHB1YmxpY1xucHJvdG8uY2xvbmUgPSBibkNsb25lXG5wcm90by5pbnRWYWx1ZSA9IGJuSW50VmFsdWVcbnByb3RvLmJ5dGVWYWx1ZSA9IGJuQnl0ZVZhbHVlXG5wcm90by5zaG9ydFZhbHVlID0gYm5TaG9ydFZhbHVlXG5wcm90by5zaWdudW0gPSBiblNpZ051bVxucHJvdG8udG9CeXRlQXJyYXkgPSBiblRvQnl0ZUFycmF5XG5wcm90by5lcXVhbHMgPSBibkVxdWFsc1xucHJvdG8ubWluID0gYm5NaW5cbnByb3RvLm1heCA9IGJuTWF4XG5wcm90by5hbmQgPSBibkFuZFxucHJvdG8ub3IgPSBibk9yXG5wcm90by54b3IgPSBiblhvclxucHJvdG8uYW5kTm90ID0gYm5BbmROb3RcbnByb3RvLm5vdCA9IGJuTm90XG5wcm90by5zaGlmdExlZnQgPSBiblNoaWZ0TGVmdFxucHJvdG8uc2hpZnRSaWdodCA9IGJuU2hpZnRSaWdodFxucHJvdG8uZ2V0TG93ZXN0U2V0Qml0ID0gYm5HZXRMb3dlc3RTZXRCaXRcbnByb3RvLmJpdENvdW50ID0gYm5CaXRDb3VudFxucHJvdG8udGVzdEJpdCA9IGJuVGVzdEJpdFxucHJvdG8uc2V0Qml0ID0gYm5TZXRCaXRcbnByb3RvLmNsZWFyQml0ID0gYm5DbGVhckJpdFxucHJvdG8uZmxpcEJpdCA9IGJuRmxpcEJpdFxucHJvdG8uYWRkID0gYm5BZGRcbnByb3RvLnN1YnRyYWN0ID0gYm5TdWJ0cmFjdFxucHJvdG8ubXVsdGlwbHkgPSBibk11bHRpcGx5XG5wcm90by5kaXZpZGUgPSBibkRpdmlkZVxucHJvdG8ucmVtYWluZGVyID0gYm5SZW1haW5kZXJcbnByb3RvLmRpdmlkZUFuZFJlbWFpbmRlciA9IGJuRGl2aWRlQW5kUmVtYWluZGVyXG5wcm90by5tb2RQb3cgPSBibk1vZFBvd1xucHJvdG8ubW9kSW52ZXJzZSA9IGJuTW9kSW52ZXJzZVxucHJvdG8ucG93ID0gYm5Qb3dcbnByb3RvLmdjZCA9IGJuR0NEXG5wcm90by5pc1Byb2JhYmxlUHJpbWUgPSBibklzUHJvYmFibGVQcmltZVxuXG4vLyBKU0JOLXNwZWNpZmljIGV4dGVuc2lvblxucHJvdG8uc3F1YXJlID0gYm5TcXVhcmVcblxuLy8gY29uc3RhbnRzXG5CaWdJbnRlZ2VyLlpFUk8gPSBuYnYoMClcbkJpZ0ludGVnZXIuT05FID0gbmJ2KDEpXG5CaWdJbnRlZ2VyLnZhbHVlT2YgPSBuYnZcblxubW9kdWxlLmV4cG9ydHMgPSBCaWdJbnRlZ2VyXG4iLCIvLyBGSVhNRTogS2luZCBvZiBhIHdlaXJkIHdheSB0byB0aHJvdyBleGNlcHRpb25zLCBjb25zaWRlciByZW1vdmluZ1xudmFyIGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpXG52YXIgQmlnSW50ZWdlciA9IHJlcXVpcmUoJy4vYmlnaScpXG5cbi8qKlxuICogVHVybnMgYSBieXRlIGFycmF5IGludG8gYSBiaWcgaW50ZWdlci5cbiAqXG4gKiBUaGlzIGZ1bmN0aW9uIHdpbGwgaW50ZXJwcmV0IGEgYnl0ZSBhcnJheSBhcyBhIGJpZyBpbnRlZ2VyIGluIGJpZ1xuICogZW5kaWFuIG5vdGF0aW9uLlxuICovXG5CaWdJbnRlZ2VyLmZyb21CeXRlQXJyYXlVbnNpZ25lZCA9IGZ1bmN0aW9uKGJ5dGVBcnJheSkge1xuICAvLyBCaWdJbnRlZ2VyIGV4cGVjdHMgYSBERVIgaW50ZWdlciBjb25mb3JtYW50IGJ5dGUgYXJyYXlcbiAgaWYgKGJ5dGVBcnJheVswXSAmIDB4ODApIHtcbiAgICByZXR1cm4gbmV3IEJpZ0ludGVnZXIoWzBdLmNvbmNhdChieXRlQXJyYXkpKVxuICB9XG5cbiAgcmV0dXJuIG5ldyBCaWdJbnRlZ2VyKGJ5dGVBcnJheSlcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgYnl0ZSBhcnJheSByZXByZXNlbnRhdGlvbiBvZiB0aGUgYmlnIGludGVnZXIuXG4gKlxuICogVGhpcyByZXR1cm5zIHRoZSBhYnNvbHV0ZSBvZiB0aGUgY29udGFpbmVkIHZhbHVlIGluIGJpZyBlbmRpYW5cbiAqIGZvcm0uIEEgdmFsdWUgb2YgemVybyByZXN1bHRzIGluIGFuIGVtcHR5IGFycmF5LlxuICovXG5CaWdJbnRlZ2VyLnByb3RvdHlwZS50b0J5dGVBcnJheVVuc2lnbmVkID0gZnVuY3Rpb24oKSB7XG4gIHZhciBieXRlQXJyYXkgPSB0aGlzLnRvQnl0ZUFycmF5KClcbiAgcmV0dXJuIGJ5dGVBcnJheVswXSA9PT0gMCA/IGJ5dGVBcnJheS5zbGljZSgxKSA6IGJ5dGVBcnJheVxufVxuXG5CaWdJbnRlZ2VyLmZyb21ERVJJbnRlZ2VyID0gZnVuY3Rpb24oYnl0ZUFycmF5KSB7XG4gIHJldHVybiBuZXcgQmlnSW50ZWdlcihieXRlQXJyYXkpXG59XG5cbi8qXG4gKiBDb252ZXJ0cyBCaWdJbnRlZ2VyIHRvIGEgREVSIGludGVnZXIgcmVwcmVzZW50YXRpb24uXG4gKlxuICogVGhlIGZvcm1hdCBmb3IgdGhpcyB2YWx1ZSB1c2VzIHRoZSBtb3N0IHNpZ25pZmljYW50IGJpdCBhcyBhIHNpZ25cbiAqIGJpdC4gIElmIHRoZSBtb3N0IHNpZ25pZmljYW50IGJpdCBpcyBhbHJlYWR5IHNldCBhbmQgdGhlIGludGVnZXIgaXNcbiAqIHBvc2l0aXZlLCBhIDB4MDAgaXMgcHJlcGVuZGVkLlxuICpcbiAqIEV4YW1wbGVzOlxuICpcbiAqICAgICAgMCA9PiAgICAgMHgwMFxuICogICAgICAxID0+ICAgICAweDAxXG4gKiAgICAgLTEgPT4gICAgIDB4ZmZcbiAqICAgIDEyNyA9PiAgICAgMHg3ZlxuICogICAtMTI3ID0+ICAgICAweDgxXG4gKiAgICAxMjggPT4gICAweDAwODBcbiAqICAgLTEyOCA9PiAgICAgMHg4MFxuICogICAgMjU1ID0+ICAgMHgwMGZmXG4gKiAgIC0yNTUgPT4gICAweGZmMDFcbiAqICAxNjMwMCA9PiAgIDB4M2ZhY1xuICogLTE2MzAwID0+ICAgMHhjMDU0XG4gKiAgNjIzMDAgPT4gMHgwMGYzNWNcbiAqIC02MjMwMCA9PiAweGZmMGNhNFxuKi9cbkJpZ0ludGVnZXIucHJvdG90eXBlLnRvREVSSW50ZWdlciA9IEJpZ0ludGVnZXIucHJvdG90eXBlLnRvQnl0ZUFycmF5XG5cbkJpZ0ludGVnZXIuZnJvbUJ1ZmZlciA9IGZ1bmN0aW9uKGJ1ZmZlcikge1xuICAvLyBCaWdJbnRlZ2VyIGV4cGVjdHMgYSBERVIgaW50ZWdlciBjb25mb3JtYW50IGJ5dGUgYXJyYXlcbiAgaWYgKGJ1ZmZlclswXSAmIDB4ODApIHtcbiAgICB2YXIgYnl0ZUFycmF5ID0gQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoYnVmZmVyKVxuXG4gICAgcmV0dXJuIG5ldyBCaWdJbnRlZ2VyKFswXS5jb25jYXQoYnl0ZUFycmF5KSlcbiAgfVxuXG4gIHJldHVybiBuZXcgQmlnSW50ZWdlcihidWZmZXIpXG59XG5cbkJpZ0ludGVnZXIuZnJvbUhleCA9IGZ1bmN0aW9uKGhleCkge1xuICBpZiAoaGV4ID09PSAnJykgcmV0dXJuIEJpZ0ludGVnZXIuWkVST1xuXG4gIGFzc2VydC5lcXVhbChoZXgsIGhleC5tYXRjaCgvXltBLUZhLWYwLTldKy8pLCAnSW52YWxpZCBoZXggc3RyaW5nJylcbiAgYXNzZXJ0LmVxdWFsKGhleC5sZW5ndGggJSAyLCAwLCAnSW5jb21wbGV0ZSBoZXgnKVxuICByZXR1cm4gbmV3IEJpZ0ludGVnZXIoaGV4LCAxNilcbn1cblxuQmlnSW50ZWdlci5wcm90b3R5cGUudG9CdWZmZXIgPSBmdW5jdGlvbihzaXplKSB7XG4gIHZhciBieXRlQXJyYXkgPSB0aGlzLnRvQnl0ZUFycmF5VW5zaWduZWQoKVxuICB2YXIgemVyb3MgPSBbXVxuXG4gIHZhciBwYWRkaW5nID0gc2l6ZSAtIGJ5dGVBcnJheS5sZW5ndGhcbiAgd2hpbGUgKHplcm9zLmxlbmd0aCA8IHBhZGRpbmcpIHplcm9zLnB1c2goMClcblxuICByZXR1cm4gbmV3IEJ1ZmZlcih6ZXJvcy5jb25jYXQoYnl0ZUFycmF5KSlcbn1cblxuQmlnSW50ZWdlci5wcm90b3R5cGUudG9IZXggPSBmdW5jdGlvbihzaXplKSB7XG4gIHJldHVybiB0aGlzLnRvQnVmZmVyKHNpemUpLnRvU3RyaW5nKCdoZXgnKVxufVxuIiwidmFyIEJpZ0ludGVnZXIgPSByZXF1aXJlKCcuL2JpZ2knKVxuXG4vL2FkZG9uc1xucmVxdWlyZSgnLi9jb252ZXJ0JylcblxubW9kdWxlLmV4cG9ydHMgPSBCaWdJbnRlZ2VyIiwibW9kdWxlLmV4cG9ydHM9e1xuICBcIl9mcm9tXCI6IFwiYmlnaUBeMS40LjFcIixcbiAgXCJfaWRcIjogXCJiaWdpQDEuNC4yXCIsXG4gIFwiX2luQnVuZGxlXCI6IGZhbHNlLFxuICBcIl9pbnRlZ3JpdHlcIjogXCJzaGExLW5HWmFsZmlMaXdqOEJjL1hNZlZoaFoxeVdDVT1cIixcbiAgXCJfbG9jYXRpb25cIjogXCIvcGVlcnBsYXlzanMtbGliL2JpZ2lcIixcbiAgXCJfcGhhbnRvbUNoaWxkcmVuXCI6IHt9LFxuICBcIl9yZXF1ZXN0ZWRcIjoge1xuICAgIFwidHlwZVwiOiBcInJhbmdlXCIsXG4gICAgXCJyZWdpc3RyeVwiOiB0cnVlLFxuICAgIFwicmF3XCI6IFwiYmlnaUBeMS40LjFcIixcbiAgICBcIm5hbWVcIjogXCJiaWdpXCIsXG4gICAgXCJlc2NhcGVkTmFtZVwiOiBcImJpZ2lcIixcbiAgICBcInJhd1NwZWNcIjogXCJeMS40LjFcIixcbiAgICBcInNhdmVTcGVjXCI6IG51bGwsXG4gICAgXCJmZXRjaFNwZWNcIjogXCJeMS40LjFcIlxuICB9LFxuICBcIl9yZXF1aXJlZEJ5XCI6IFtcbiAgICBcIi9wZWVycGxheXNqcy1saWJcIixcbiAgICBcIi9wZWVycGxheXNqcy1saWIvZWN1cnZlXCJcbiAgXSxcbiAgXCJfcmVzb2x2ZWRcIjogXCJodHRwczovL3JlZ2lzdHJ5Lm5wbWpzLm9yZy9iaWdpLy0vYmlnaS0xLjQuMi50Z3pcIixcbiAgXCJfc2hhc3VtXCI6IFwiOWM2NjVhOTVmODhiOGIwOGZjMDVjZmQ3MzFmNTYxODU5ZDcyNTgyNVwiLFxuICBcIl9zcGVjXCI6IFwiYmlnaUBeMS40LjFcIixcbiAgXCJfd2hlcmVcIjogXCIvVXNlcnMvbXNlYXdhcmQvRG9jdW1lbnRzL2NvZGUvcGVlcnBsYXlzanMtbGliXCIsXG4gIFwiYnVnc1wiOiB7XG4gICAgXCJ1cmxcIjogXCJodHRwczovL2dpdGh1Yi5jb20vY3J5cHRvY29pbmpzL2JpZ2kvaXNzdWVzXCJcbiAgfSxcbiAgXCJidW5kbGVEZXBlbmRlbmNpZXNcIjogZmFsc2UsXG4gIFwiZGVwZW5kZW5jaWVzXCI6IHt9LFxuICBcImRlcHJlY2F0ZWRcIjogZmFsc2UsXG4gIFwiZGVzY3JpcHRpb25cIjogXCJCaWcgaW50ZWdlcnMuXCIsXG4gIFwiZGV2RGVwZW5kZW5jaWVzXCI6IHtcbiAgICBcImNvdmVyYWxsc1wiOiBcIl4yLjExLjJcIixcbiAgICBcImlzdGFuYnVsXCI6IFwiXjAuMy41XCIsXG4gICAgXCJqc2hpbnRcIjogXCJeMi41LjFcIixcbiAgICBcIm1vY2hhXCI6IFwiXjIuMS4wXCIsXG4gICAgXCJtb2NoaWZ5XCI6IFwiXjIuMS4wXCJcbiAgfSxcbiAgXCJob21lcGFnZVwiOiBcImh0dHBzOi8vZ2l0aHViLmNvbS9jcnlwdG9jb2luanMvYmlnaSNyZWFkbWVcIixcbiAgXCJrZXl3b3Jkc1wiOiBbXG4gICAgXCJjcnlwdG9ncmFwaHlcIixcbiAgICBcIm1hdGhcIixcbiAgICBcImJpdGNvaW5cIixcbiAgICBcImFyYml0cmFyeVwiLFxuICAgIFwicHJlY2lzaW9uXCIsXG4gICAgXCJhcml0aG1ldGljXCIsXG4gICAgXCJiaWdcIixcbiAgICBcImludGVnZXJcIixcbiAgICBcImludFwiLFxuICAgIFwibnVtYmVyXCIsXG4gICAgXCJiaWdpbnRlZ2VyXCIsXG4gICAgXCJiaWdpbnRcIixcbiAgICBcImJpZ251bWJlclwiLFxuICAgIFwiZGVjaW1hbFwiLFxuICAgIFwiZmxvYXRcIlxuICBdLFxuICBcIm1haW5cIjogXCIuL2xpYi9pbmRleC5qc1wiLFxuICBcIm5hbWVcIjogXCJiaWdpXCIsXG4gIFwicmVwb3NpdG9yeVwiOiB7XG4gICAgXCJ1cmxcIjogXCJnaXQraHR0cHM6Ly9naXRodWIuY29tL2NyeXB0b2NvaW5qcy9iaWdpLmdpdFwiLFxuICAgIFwidHlwZVwiOiBcImdpdFwiXG4gIH0sXG4gIFwic2NyaXB0c1wiOiB7XG4gICAgXCJicm93c2VyLXRlc3RcIjogXCJtb2NoaWZ5IC0td2QgLVIgc3BlY1wiLFxuICAgIFwiY292ZXJhZ2VcIjogXCJpc3RhbmJ1bCBjb3ZlciAuL25vZGVfbW9kdWxlcy8uYmluL19tb2NoYSAtLSAtLXJlcG9ydGVyIGxpc3QgdGVzdC8qLmpzXCIsXG4gICAgXCJjb3ZlcmFsbHNcIjogXCJucG0gcnVuLXNjcmlwdCBjb3ZlcmFnZSAmJiBub2RlIC4vbm9kZV9tb2R1bGVzLy5iaW4vY292ZXJhbGxzIDwgY292ZXJhZ2UvbGNvdi5pbmZvXCIsXG4gICAgXCJqc2hpbnRcIjogXCJqc2hpbnQgLS1jb25maWcganNoaW50Lmpzb24gbGliLyouanMgOyB0cnVlXCIsXG4gICAgXCJ0ZXN0XCI6IFwiX21vY2hhIC0tIHRlc3QvKi5qc1wiLFxuICAgIFwidW5pdFwiOiBcIm1vY2hhXCJcbiAgfSxcbiAgXCJ0ZXN0bGluZ1wiOiB7XG4gICAgXCJmaWxlc1wiOiBcInRlc3QvKi5qc1wiLFxuICAgIFwiaGFybmVzc1wiOiBcIm1vY2hhXCIsXG4gICAgXCJicm93c2Vyc1wiOiBbXG4gICAgICBcImllLzkuLmxhdGVzdFwiLFxuICAgICAgXCJmaXJlZm94L2xhdGVzdFwiLFxuICAgICAgXCJjaHJvbWUvbGF0ZXN0XCIsXG4gICAgICBcInNhZmFyaS82LjAuLmxhdGVzdFwiLFxuICAgICAgXCJpcGhvbmUvNi4wLi5sYXRlc3RcIixcbiAgICAgIFwiYW5kcm9pZC1icm93c2VyLzQuMi4ubGF0ZXN0XCJcbiAgICBdXG4gIH0sXG4gIFwidmVyc2lvblwiOiBcIjEuNC4yXCJcbn1cbiIsIiIsIi8qIVxuICogVGhlIGJ1ZmZlciBtb2R1bGUgZnJvbSBub2RlLmpzLCBmb3IgdGhlIGJyb3dzZXIuXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGZlcm9zc0BmZXJvc3Mub3JnPiA8aHR0cDovL2Zlcm9zcy5vcmc+XG4gKiBAbGljZW5zZSAgTUlUXG4gKi9cbi8qIGVzbGludC1kaXNhYmxlIG5vLXByb3RvICovXG5cbid1c2Ugc3RyaWN0J1xuXG52YXIgYmFzZTY0ID0gcmVxdWlyZSgnYmFzZTY0LWpzJylcbnZhciBpZWVlNzU0ID0gcmVxdWlyZSgnaWVlZTc1NCcpXG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJ2lzYXJyYXknKVxuXG5leHBvcnRzLkJ1ZmZlciA9IEJ1ZmZlclxuZXhwb3J0cy5TbG93QnVmZmVyID0gU2xvd0J1ZmZlclxuZXhwb3J0cy5JTlNQRUNUX01BWF9CWVRFUyA9IDUwXG5cbi8qKlxuICogSWYgYEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUYDpcbiAqICAgPT09IHRydWUgICAgVXNlIFVpbnQ4QXJyYXkgaW1wbGVtZW50YXRpb24gKGZhc3Rlc3QpXG4gKiAgID09PSBmYWxzZSAgIFVzZSBPYmplY3QgaW1wbGVtZW50YXRpb24gKG1vc3QgY29tcGF0aWJsZSwgZXZlbiBJRTYpXG4gKlxuICogQnJvd3NlcnMgdGhhdCBzdXBwb3J0IHR5cGVkIGFycmF5cyBhcmUgSUUgMTArLCBGaXJlZm94IDQrLCBDaHJvbWUgNyssIFNhZmFyaSA1LjErLFxuICogT3BlcmEgMTEuNissIGlPUyA0LjIrLlxuICpcbiAqIER1ZSB0byB2YXJpb3VzIGJyb3dzZXIgYnVncywgc29tZXRpbWVzIHRoZSBPYmplY3QgaW1wbGVtZW50YXRpb24gd2lsbCBiZSB1c2VkIGV2ZW5cbiAqIHdoZW4gdGhlIGJyb3dzZXIgc3VwcG9ydHMgdHlwZWQgYXJyYXlzLlxuICpcbiAqIE5vdGU6XG4gKlxuICogICAtIEZpcmVmb3ggNC0yOSBsYWNrcyBzdXBwb3J0IGZvciBhZGRpbmcgbmV3IHByb3BlcnRpZXMgdG8gYFVpbnQ4QXJyYXlgIGluc3RhbmNlcyxcbiAqICAgICBTZWU6IGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTY5NTQzOC5cbiAqXG4gKiAgIC0gQ2hyb21lIDktMTAgaXMgbWlzc2luZyB0aGUgYFR5cGVkQXJyYXkucHJvdG90eXBlLnN1YmFycmF5YCBmdW5jdGlvbi5cbiAqXG4gKiAgIC0gSUUxMCBoYXMgYSBicm9rZW4gYFR5cGVkQXJyYXkucHJvdG90eXBlLnN1YmFycmF5YCBmdW5jdGlvbiB3aGljaCByZXR1cm5zIGFycmF5cyBvZlxuICogICAgIGluY29ycmVjdCBsZW5ndGggaW4gc29tZSBzaXR1YXRpb25zLlxuXG4gKiBXZSBkZXRlY3QgdGhlc2UgYnVnZ3kgYnJvd3NlcnMgYW5kIHNldCBgQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlRgIHRvIGBmYWxzZWAgc28gdGhleVxuICogZ2V0IHRoZSBPYmplY3QgaW1wbGVtZW50YXRpb24sIHdoaWNoIGlzIHNsb3dlciBidXQgYmVoYXZlcyBjb3JyZWN0bHkuXG4gKi9cbkJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUID0gZ2xvYmFsLlRZUEVEX0FSUkFZX1NVUFBPUlQgIT09IHVuZGVmaW5lZFxuICA/IGdsb2JhbC5UWVBFRF9BUlJBWV9TVVBQT1JUXG4gIDogdHlwZWRBcnJheVN1cHBvcnQoKVxuXG4vKlxuICogRXhwb3J0IGtNYXhMZW5ndGggYWZ0ZXIgdHlwZWQgYXJyYXkgc3VwcG9ydCBpcyBkZXRlcm1pbmVkLlxuICovXG5leHBvcnRzLmtNYXhMZW5ndGggPSBrTWF4TGVuZ3RoKClcblxuZnVuY3Rpb24gdHlwZWRBcnJheVN1cHBvcnQgKCkge1xuICB0cnkge1xuICAgIHZhciBhcnIgPSBuZXcgVWludDhBcnJheSgxKVxuICAgIGFyci5fX3Byb3RvX18gPSB7X19wcm90b19fOiBVaW50OEFycmF5LnByb3RvdHlwZSwgZm9vOiBmdW5jdGlvbiAoKSB7IHJldHVybiA0MiB9fVxuICAgIHJldHVybiBhcnIuZm9vKCkgPT09IDQyICYmIC8vIHR5cGVkIGFycmF5IGluc3RhbmNlcyBjYW4gYmUgYXVnbWVudGVkXG4gICAgICAgIHR5cGVvZiBhcnIuc3ViYXJyYXkgPT09ICdmdW5jdGlvbicgJiYgLy8gY2hyb21lIDktMTAgbGFjayBgc3ViYXJyYXlgXG4gICAgICAgIGFyci5zdWJhcnJheSgxLCAxKS5ieXRlTGVuZ3RoID09PSAwIC8vIGllMTAgaGFzIGJyb2tlbiBgc3ViYXJyYXlgXG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5mdW5jdGlvbiBrTWF4TGVuZ3RoICgpIHtcbiAgcmV0dXJuIEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUXG4gICAgPyAweDdmZmZmZmZmXG4gICAgOiAweDNmZmZmZmZmXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZUJ1ZmZlciAodGhhdCwgbGVuZ3RoKSB7XG4gIGlmIChrTWF4TGVuZ3RoKCkgPCBsZW5ndGgpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW52YWxpZCB0eXBlZCBhcnJheSBsZW5ndGgnKVxuICB9XG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlLCBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoYXQgPSBuZXcgVWludDhBcnJheShsZW5ndGgpXG4gICAgdGhhdC5fX3Byb3RvX18gPSBCdWZmZXIucHJvdG90eXBlXG4gIH0gZWxzZSB7XG4gICAgLy8gRmFsbGJhY2s6IFJldHVybiBhbiBvYmplY3QgaW5zdGFuY2Ugb2YgdGhlIEJ1ZmZlciBjbGFzc1xuICAgIGlmICh0aGF0ID09PSBudWxsKSB7XG4gICAgICB0aGF0ID0gbmV3IEJ1ZmZlcihsZW5ndGgpXG4gICAgfVxuICAgIHRoYXQubGVuZ3RoID0gbGVuZ3RoXG4gIH1cblxuICByZXR1cm4gdGhhdFxufVxuXG4vKipcbiAqIFRoZSBCdWZmZXIgY29uc3RydWN0b3IgcmV0dXJucyBpbnN0YW5jZXMgb2YgYFVpbnQ4QXJyYXlgIHRoYXQgaGF2ZSB0aGVpclxuICogcHJvdG90eXBlIGNoYW5nZWQgdG8gYEJ1ZmZlci5wcm90b3R5cGVgLiBGdXJ0aGVybW9yZSwgYEJ1ZmZlcmAgaXMgYSBzdWJjbGFzcyBvZlxuICogYFVpbnQ4QXJyYXlgLCBzbyB0aGUgcmV0dXJuZWQgaW5zdGFuY2VzIHdpbGwgaGF2ZSBhbGwgdGhlIG5vZGUgYEJ1ZmZlcmAgbWV0aG9kc1xuICogYW5kIHRoZSBgVWludDhBcnJheWAgbWV0aG9kcy4gU3F1YXJlIGJyYWNrZXQgbm90YXRpb24gd29ya3MgYXMgZXhwZWN0ZWQgLS0gaXRcbiAqIHJldHVybnMgYSBzaW5nbGUgb2N0ZXQuXG4gKlxuICogVGhlIGBVaW50OEFycmF5YCBwcm90b3R5cGUgcmVtYWlucyB1bm1vZGlmaWVkLlxuICovXG5cbmZ1bmN0aW9uIEJ1ZmZlciAoYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgaWYgKCFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCAmJiAhKHRoaXMgaW5zdGFuY2VvZiBCdWZmZXIpKSB7XG4gICAgcmV0dXJuIG5ldyBCdWZmZXIoYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICAvLyBDb21tb24gY2FzZS5cbiAgaWYgKHR5cGVvZiBhcmcgPT09ICdudW1iZXInKSB7XG4gICAgaWYgKHR5cGVvZiBlbmNvZGluZ09yT2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAnSWYgZW5jb2RpbmcgaXMgc3BlY2lmaWVkIHRoZW4gdGhlIGZpcnN0IGFyZ3VtZW50IG11c3QgYmUgYSBzdHJpbmcnXG4gICAgICApXG4gICAgfVxuICAgIHJldHVybiBhbGxvY1Vuc2FmZSh0aGlzLCBhcmcpXG4gIH1cbiAgcmV0dXJuIGZyb20odGhpcywgYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG59XG5cbkJ1ZmZlci5wb29sU2l6ZSA9IDgxOTIgLy8gbm90IHVzZWQgYnkgdGhpcyBpbXBsZW1lbnRhdGlvblxuXG4vLyBUT0RPOiBMZWdhY3ksIG5vdCBuZWVkZWQgYW55bW9yZS4gUmVtb3ZlIGluIG5leHQgbWFqb3IgdmVyc2lvbi5cbkJ1ZmZlci5fYXVnbWVudCA9IGZ1bmN0aW9uIChhcnIpIHtcbiAgYXJyLl9fcHJvdG9fXyA9IEJ1ZmZlci5wcm90b3R5cGVcbiAgcmV0dXJuIGFyclxufVxuXG5mdW5jdGlvbiBmcm9tICh0aGF0LCB2YWx1ZSwgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKSB7XG4gIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJ2YWx1ZVwiIGFyZ3VtZW50IG11c3Qgbm90IGJlIGEgbnVtYmVyJylcbiAgfVxuXG4gIGlmICh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmIHZhbHVlIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpIHtcbiAgICByZXR1cm4gZnJvbUFycmF5QnVmZmVyKHRoYXQsIHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG4gIH1cblxuICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiBmcm9tU3RyaW5nKHRoYXQsIHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0KVxuICB9XG5cbiAgcmV0dXJuIGZyb21PYmplY3QodGhhdCwgdmFsdWUpXG59XG5cbi8qKlxuICogRnVuY3Rpb25hbGx5IGVxdWl2YWxlbnQgdG8gQnVmZmVyKGFyZywgZW5jb2RpbmcpIGJ1dCB0aHJvd3MgYSBUeXBlRXJyb3JcbiAqIGlmIHZhbHVlIGlzIGEgbnVtYmVyLlxuICogQnVmZmVyLmZyb20oc3RyWywgZW5jb2RpbmddKVxuICogQnVmZmVyLmZyb20oYXJyYXkpXG4gKiBCdWZmZXIuZnJvbShidWZmZXIpXG4gKiBCdWZmZXIuZnJvbShhcnJheUJ1ZmZlclssIGJ5dGVPZmZzZXRbLCBsZW5ndGhdXSlcbiAqKi9cbkJ1ZmZlci5mcm9tID0gZnVuY3Rpb24gKHZhbHVlLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGZyb20obnVsbCwgdmFsdWUsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbn1cblxuaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gIEJ1ZmZlci5wcm90b3R5cGUuX19wcm90b19fID0gVWludDhBcnJheS5wcm90b3R5cGVcbiAgQnVmZmVyLl9fcHJvdG9fXyA9IFVpbnQ4QXJyYXlcbiAgaWYgKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC5zcGVjaWVzICYmXG4gICAgICBCdWZmZXJbU3ltYm9sLnNwZWNpZXNdID09PSBCdWZmZXIpIHtcbiAgICAvLyBGaXggc3ViYXJyYXkoKSBpbiBFUzIwMTYuIFNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9idWZmZXIvcHVsbC85N1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShCdWZmZXIsIFN5bWJvbC5zcGVjaWVzLCB7XG4gICAgICB2YWx1ZTogbnVsbCxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgIH0pXG4gIH1cbn1cblxuZnVuY3Rpb24gYXNzZXJ0U2l6ZSAoc2l6ZSkge1xuICBpZiAodHlwZW9mIHNpemUgIT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJzaXplXCIgYXJndW1lbnQgbXVzdCBiZSBhIG51bWJlcicpXG4gIH0gZWxzZSBpZiAoc2l6ZSA8IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXCJzaXplXCIgYXJndW1lbnQgbXVzdCBub3QgYmUgbmVnYXRpdmUnKVxuICB9XG59XG5cbmZ1bmN0aW9uIGFsbG9jICh0aGF0LCBzaXplLCBmaWxsLCBlbmNvZGluZykge1xuICBhc3NlcnRTaXplKHNpemUpXG4gIGlmIChzaXplIDw9IDApIHtcbiAgICByZXR1cm4gY3JlYXRlQnVmZmVyKHRoYXQsIHNpemUpXG4gIH1cbiAgaWYgKGZpbGwgIT09IHVuZGVmaW5lZCkge1xuICAgIC8vIE9ubHkgcGF5IGF0dGVudGlvbiB0byBlbmNvZGluZyBpZiBpdCdzIGEgc3RyaW5nLiBUaGlzXG4gICAgLy8gcHJldmVudHMgYWNjaWRlbnRhbGx5IHNlbmRpbmcgaW4gYSBudW1iZXIgdGhhdCB3b3VsZFxuICAgIC8vIGJlIGludGVycHJldHRlZCBhcyBhIHN0YXJ0IG9mZnNldC5cbiAgICByZXR1cm4gdHlwZW9mIGVuY29kaW5nID09PSAnc3RyaW5nJ1xuICAgICAgPyBjcmVhdGVCdWZmZXIodGhhdCwgc2l6ZSkuZmlsbChmaWxsLCBlbmNvZGluZylcbiAgICAgIDogY3JlYXRlQnVmZmVyKHRoYXQsIHNpemUpLmZpbGwoZmlsbClcbiAgfVxuICByZXR1cm4gY3JlYXRlQnVmZmVyKHRoYXQsIHNpemUpXG59XG5cbi8qKlxuICogQ3JlYXRlcyBhIG5ldyBmaWxsZWQgQnVmZmVyIGluc3RhbmNlLlxuICogYWxsb2Moc2l6ZVssIGZpbGxbLCBlbmNvZGluZ11dKVxuICoqL1xuQnVmZmVyLmFsbG9jID0gZnVuY3Rpb24gKHNpemUsIGZpbGwsIGVuY29kaW5nKSB7XG4gIHJldHVybiBhbGxvYyhudWxsLCBzaXplLCBmaWxsLCBlbmNvZGluZylcbn1cblxuZnVuY3Rpb24gYWxsb2NVbnNhZmUgKHRoYXQsIHNpemUpIHtcbiAgYXNzZXJ0U2l6ZShzaXplKVxuICB0aGF0ID0gY3JlYXRlQnVmZmVyKHRoYXQsIHNpemUgPCAwID8gMCA6IGNoZWNrZWQoc2l6ZSkgfCAwKVxuICBpZiAoIUJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaXplOyArK2kpIHtcbiAgICAgIHRoYXRbaV0gPSAwXG4gICAgfVxuICB9XG4gIHJldHVybiB0aGF0XG59XG5cbi8qKlxuICogRXF1aXZhbGVudCB0byBCdWZmZXIobnVtKSwgYnkgZGVmYXVsdCBjcmVhdGVzIGEgbm9uLXplcm8tZmlsbGVkIEJ1ZmZlciBpbnN0YW5jZS5cbiAqICovXG5CdWZmZXIuYWxsb2NVbnNhZmUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUobnVsbCwgc2l6ZSlcbn1cbi8qKlxuICogRXF1aXZhbGVudCB0byBTbG93QnVmZmVyKG51bSksIGJ5IGRlZmF1bHQgY3JlYXRlcyBhIG5vbi16ZXJvLWZpbGxlZCBCdWZmZXIgaW5zdGFuY2UuXG4gKi9cbkJ1ZmZlci5hbGxvY1Vuc2FmZVNsb3cgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICByZXR1cm4gYWxsb2NVbnNhZmUobnVsbCwgc2l6ZSlcbn1cblxuZnVuY3Rpb24gZnJvbVN0cmluZyAodGhhdCwgc3RyaW5nLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJyB8fCBlbmNvZGluZyA9PT0gJycpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICB9XG5cbiAgaWYgKCFCdWZmZXIuaXNFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImVuY29kaW5nXCIgbXVzdCBiZSBhIHZhbGlkIHN0cmluZyBlbmNvZGluZycpXG4gIH1cblxuICB2YXIgbGVuZ3RoID0gYnl0ZUxlbmd0aChzdHJpbmcsIGVuY29kaW5nKSB8IDBcbiAgdGhhdCA9IGNyZWF0ZUJ1ZmZlcih0aGF0LCBsZW5ndGgpXG5cbiAgdmFyIGFjdHVhbCA9IHRoYXQud3JpdGUoc3RyaW5nLCBlbmNvZGluZylcblxuICBpZiAoYWN0dWFsICE9PSBsZW5ndGgpIHtcbiAgICAvLyBXcml0aW5nIGEgaGV4IHN0cmluZywgZm9yIGV4YW1wbGUsIHRoYXQgY29udGFpbnMgaW52YWxpZCBjaGFyYWN0ZXJzIHdpbGxcbiAgICAvLyBjYXVzZSBldmVyeXRoaW5nIGFmdGVyIHRoZSBmaXJzdCBpbnZhbGlkIGNoYXJhY3RlciB0byBiZSBpZ25vcmVkLiAoZS5nLlxuICAgIC8vICdhYnh4Y2QnIHdpbGwgYmUgdHJlYXRlZCBhcyAnYWInKVxuICAgIHRoYXQgPSB0aGF0LnNsaWNlKDAsIGFjdHVhbClcbiAgfVxuXG4gIHJldHVybiB0aGF0XG59XG5cbmZ1bmN0aW9uIGZyb21BcnJheUxpa2UgKHRoYXQsIGFycmF5KSB7XG4gIHZhciBsZW5ndGggPSBhcnJheS5sZW5ndGggPCAwID8gMCA6IGNoZWNrZWQoYXJyYXkubGVuZ3RoKSB8IDBcbiAgdGhhdCA9IGNyZWF0ZUJ1ZmZlcih0aGF0LCBsZW5ndGgpXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyBpICs9IDEpIHtcbiAgICB0aGF0W2ldID0gYXJyYXlbaV0gJiAyNTVcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tQXJyYXlCdWZmZXIgKHRoYXQsIGFycmF5LCBieXRlT2Zmc2V0LCBsZW5ndGgpIHtcbiAgYXJyYXkuYnl0ZUxlbmd0aCAvLyB0aGlzIHRocm93cyBpZiBgYXJyYXlgIGlzIG5vdCBhIHZhbGlkIEFycmF5QnVmZmVyXG5cbiAgaWYgKGJ5dGVPZmZzZXQgPCAwIHx8IGFycmF5LmJ5dGVMZW5ndGggPCBieXRlT2Zmc2V0KSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1xcJ29mZnNldFxcJyBpcyBvdXQgb2YgYm91bmRzJylcbiAgfVxuXG4gIGlmIChhcnJheS5ieXRlTGVuZ3RoIDwgYnl0ZU9mZnNldCArIChsZW5ndGggfHwgMCkpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignXFwnbGVuZ3RoXFwnIGlzIG91dCBvZiBib3VuZHMnKVxuICB9XG5cbiAgaWYgKGJ5dGVPZmZzZXQgPT09IHVuZGVmaW5lZCAmJiBsZW5ndGggPT09IHVuZGVmaW5lZCkge1xuICAgIGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXkpXG4gIH0gZWxzZSBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBhcnJheSA9IG5ldyBVaW50OEFycmF5KGFycmF5LCBieXRlT2Zmc2V0KVxuICB9IGVsc2Uge1xuICAgIGFycmF5ID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXksIGJ5dGVPZmZzZXQsIGxlbmd0aClcbiAgfVxuXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIFJldHVybiBhbiBhdWdtZW50ZWQgYFVpbnQ4QXJyYXlgIGluc3RhbmNlLCBmb3IgYmVzdCBwZXJmb3JtYW5jZVxuICAgIHRoYXQgPSBhcnJheVxuICAgIHRoYXQuX19wcm90b19fID0gQnVmZmVyLnByb3RvdHlwZVxuICB9IGVsc2Uge1xuICAgIC8vIEZhbGxiYWNrOiBSZXR1cm4gYW4gb2JqZWN0IGluc3RhbmNlIG9mIHRoZSBCdWZmZXIgY2xhc3NcbiAgICB0aGF0ID0gZnJvbUFycmF5TGlrZSh0aGF0LCBhcnJheSlcbiAgfVxuICByZXR1cm4gdGhhdFxufVxuXG5mdW5jdGlvbiBmcm9tT2JqZWN0ICh0aGF0LCBvYmopIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihvYmopKSB7XG4gICAgdmFyIGxlbiA9IGNoZWNrZWQob2JqLmxlbmd0aCkgfCAwXG4gICAgdGhhdCA9IGNyZWF0ZUJ1ZmZlcih0aGF0LCBsZW4pXG5cbiAgICBpZiAodGhhdC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiB0aGF0XG4gICAgfVxuXG4gICAgb2JqLmNvcHkodGhhdCwgMCwgMCwgbGVuKVxuICAgIHJldHVybiB0aGF0XG4gIH1cblxuICBpZiAob2JqKSB7XG4gICAgaWYgKCh0eXBlb2YgQXJyYXlCdWZmZXIgIT09ICd1bmRlZmluZWQnICYmXG4gICAgICAgIG9iai5idWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgfHwgJ2xlbmd0aCcgaW4gb2JqKSB7XG4gICAgICBpZiAodHlwZW9mIG9iai5sZW5ndGggIT09ICdudW1iZXInIHx8IGlzbmFuKG9iai5sZW5ndGgpKSB7XG4gICAgICAgIHJldHVybiBjcmVhdGVCdWZmZXIodGhhdCwgMClcbiAgICAgIH1cbiAgICAgIHJldHVybiBmcm9tQXJyYXlMaWtlKHRoYXQsIG9iailcbiAgICB9XG5cbiAgICBpZiAob2JqLnR5cGUgPT09ICdCdWZmZXInICYmIGlzQXJyYXkob2JqLmRhdGEpKSB7XG4gICAgICByZXR1cm4gZnJvbUFycmF5TGlrZSh0aGF0LCBvYmouZGF0YSlcbiAgICB9XG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCdGaXJzdCBhcmd1bWVudCBtdXN0IGJlIGEgc3RyaW5nLCBCdWZmZXIsIEFycmF5QnVmZmVyLCBBcnJheSwgb3IgYXJyYXktbGlrZSBvYmplY3QuJylcbn1cblxuZnVuY3Rpb24gY2hlY2tlZCAobGVuZ3RoKSB7XG4gIC8vIE5vdGU6IGNhbm5vdCB1c2UgYGxlbmd0aCA8IGtNYXhMZW5ndGgoKWAgaGVyZSBiZWNhdXNlIHRoYXQgZmFpbHMgd2hlblxuICAvLyBsZW5ndGggaXMgTmFOICh3aGljaCBpcyBvdGhlcndpc2UgY29lcmNlZCB0byB6ZXJvLilcbiAgaWYgKGxlbmd0aCA+PSBrTWF4TGVuZ3RoKCkpIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQXR0ZW1wdCB0byBhbGxvY2F0ZSBCdWZmZXIgbGFyZ2VyIHRoYW4gbWF4aW11bSAnICtcbiAgICAgICAgICAgICAgICAgICAgICAgICAnc2l6ZTogMHgnICsga01heExlbmd0aCgpLnRvU3RyaW5nKDE2KSArICcgYnl0ZXMnKVxuICB9XG4gIHJldHVybiBsZW5ndGggfCAwXG59XG5cbmZ1bmN0aW9uIFNsb3dCdWZmZXIgKGxlbmd0aCkge1xuICBpZiAoK2xlbmd0aCAhPSBsZW5ndGgpIHsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBlcWVxZXFcbiAgICBsZW5ndGggPSAwXG4gIH1cbiAgcmV0dXJuIEJ1ZmZlci5hbGxvYygrbGVuZ3RoKVxufVxuXG5CdWZmZXIuaXNCdWZmZXIgPSBmdW5jdGlvbiBpc0J1ZmZlciAoYikge1xuICByZXR1cm4gISEoYiAhPSBudWxsICYmIGIuX2lzQnVmZmVyKVxufVxuXG5CdWZmZXIuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKGEsIGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYSkgfHwgIUJ1ZmZlci5pc0J1ZmZlcihiKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50cyBtdXN0IGJlIEJ1ZmZlcnMnKVxuICB9XG5cbiAgaWYgKGEgPT09IGIpIHJldHVybiAwXG5cbiAgdmFyIHggPSBhLmxlbmd0aFxuICB2YXIgeSA9IGIubGVuZ3RoXG5cbiAgZm9yICh2YXIgaSA9IDAsIGxlbiA9IE1hdGgubWluKHgsIHkpOyBpIDwgbGVuOyArK2kpIHtcbiAgICBpZiAoYVtpXSAhPT0gYltpXSkge1xuICAgICAgeCA9IGFbaV1cbiAgICAgIHkgPSBiW2ldXG4gICAgICBicmVha1xuICAgIH1cbiAgfVxuXG4gIGlmICh4IDwgeSkgcmV0dXJuIC0xXG4gIGlmICh5IDwgeCkgcmV0dXJuIDFcbiAgcmV0dXJuIDBcbn1cblxuQnVmZmVyLmlzRW5jb2RpbmcgPSBmdW5jdGlvbiBpc0VuY29kaW5nIChlbmNvZGluZykge1xuICBzd2l0Y2ggKFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKSkge1xuICAgIGNhc2UgJ2hleCc6XG4gICAgY2FzZSAndXRmOCc6XG4gICAgY2FzZSAndXRmLTgnOlxuICAgIGNhc2UgJ2FzY2lpJzpcbiAgICBjYXNlICdsYXRpbjEnOlxuICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgY2FzZSAnYmFzZTY0JzpcbiAgICBjYXNlICd1Y3MyJzpcbiAgICBjYXNlICd1Y3MtMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgcmV0dXJuIHRydWVcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZhbHNlXG4gIH1cbn1cblxuQnVmZmVyLmNvbmNhdCA9IGZ1bmN0aW9uIGNvbmNhdCAobGlzdCwgbGVuZ3RoKSB7XG4gIGlmICghaXNBcnJheShsaXN0KSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wibGlzdFwiIGFyZ3VtZW50IG11c3QgYmUgYW4gQXJyYXkgb2YgQnVmZmVycycpXG4gIH1cblxuICBpZiAobGlzdC5sZW5ndGggPT09IDApIHtcbiAgICByZXR1cm4gQnVmZmVyLmFsbG9jKDApXG4gIH1cblxuICB2YXIgaVxuICBpZiAobGVuZ3RoID09PSB1bmRlZmluZWQpIHtcbiAgICBsZW5ndGggPSAwXG4gICAgZm9yIChpID0gMDsgaSA8IGxpc3QubGVuZ3RoOyArK2kpIHtcbiAgICAgIGxlbmd0aCArPSBsaXN0W2ldLmxlbmd0aFxuICAgIH1cbiAgfVxuXG4gIHZhciBidWZmZXIgPSBCdWZmZXIuYWxsb2NVbnNhZmUobGVuZ3RoKVxuICB2YXIgcG9zID0gMFxuICBmb3IgKGkgPSAwOyBpIDwgbGlzdC5sZW5ndGg7ICsraSkge1xuICAgIHZhciBidWYgPSBsaXN0W2ldXG4gICAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYnVmKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignXCJsaXN0XCIgYXJndW1lbnQgbXVzdCBiZSBhbiBBcnJheSBvZiBCdWZmZXJzJylcbiAgICB9XG4gICAgYnVmLmNvcHkoYnVmZmVyLCBwb3MpXG4gICAgcG9zICs9IGJ1Zi5sZW5ndGhcbiAgfVxuICByZXR1cm4gYnVmZmVyXG59XG5cbmZ1bmN0aW9uIGJ5dGVMZW5ndGggKHN0cmluZywgZW5jb2RpbmcpIHtcbiAgaWYgKEJ1ZmZlci5pc0J1ZmZlcihzdHJpbmcpKSB7XG4gICAgcmV0dXJuIHN0cmluZy5sZW5ndGhcbiAgfVxuICBpZiAodHlwZW9mIEFycmF5QnVmZmVyICE9PSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgQXJyYXlCdWZmZXIuaXNWaWV3ID09PSAnZnVuY3Rpb24nICYmXG4gICAgICAoQXJyYXlCdWZmZXIuaXNWaWV3KHN0cmluZykgfHwgc3RyaW5nIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIpKSB7XG4gICAgcmV0dXJuIHN0cmluZy5ieXRlTGVuZ3RoXG4gIH1cbiAgaWYgKHR5cGVvZiBzdHJpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgc3RyaW5nID0gJycgKyBzdHJpbmdcbiAgfVxuXG4gIHZhciBsZW4gPSBzdHJpbmcubGVuZ3RoXG4gIGlmIChsZW4gPT09IDApIHJldHVybiAwXG5cbiAgLy8gVXNlIGEgZm9yIGxvb3AgdG8gYXZvaWQgcmVjdXJzaW9uXG4gIHZhciBsb3dlcmVkQ2FzZSA9IGZhbHNlXG4gIGZvciAoOzspIHtcbiAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICBjYXNlICdsYXRpbjEnOlxuICAgICAgY2FzZSAnYmluYXJ5JzpcbiAgICAgICAgcmV0dXJuIGxlblxuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICBjYXNlIHVuZGVmaW5lZDpcbiAgICAgICAgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoXG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gbGVuICogMlxuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGxlbiA+Pj4gMVxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgcmV0dXJuIGJhc2U2NFRvQnl0ZXMoc3RyaW5nKS5sZW5ndGhcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGlmIChsb3dlcmVkQ2FzZSkgcmV0dXJuIHV0ZjhUb0J5dGVzKHN0cmluZykubGVuZ3RoIC8vIGFzc3VtZSB1dGY4XG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5CdWZmZXIuYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGhcblxuZnVuY3Rpb24gc2xvd1RvU3RyaW5nIChlbmNvZGluZywgc3RhcnQsIGVuZCkge1xuICB2YXIgbG93ZXJlZENhc2UgPSBmYWxzZVxuXG4gIC8vIE5vIG5lZWQgdG8gdmVyaWZ5IHRoYXQgXCJ0aGlzLmxlbmd0aCA8PSBNQVhfVUlOVDMyXCIgc2luY2UgaXQncyBhIHJlYWQtb25seVxuICAvLyBwcm9wZXJ0eSBvZiBhIHR5cGVkIGFycmF5LlxuXG4gIC8vIFRoaXMgYmVoYXZlcyBuZWl0aGVyIGxpa2UgU3RyaW5nIG5vciBVaW50OEFycmF5IGluIHRoYXQgd2Ugc2V0IHN0YXJ0L2VuZFxuICAvLyB0byB0aGVpciB1cHBlci9sb3dlciBib3VuZHMgaWYgdGhlIHZhbHVlIHBhc3NlZCBpcyBvdXQgb2YgcmFuZ2UuXG4gIC8vIHVuZGVmaW5lZCBpcyBoYW5kbGVkIHNwZWNpYWxseSBhcyBwZXIgRUNNQS0yNjIgNnRoIEVkaXRpb24sXG4gIC8vIFNlY3Rpb24gMTMuMy4zLjcgUnVudGltZSBTZW1hbnRpY3M6IEtleWVkQmluZGluZ0luaXRpYWxpemF0aW9uLlxuICBpZiAoc3RhcnQgPT09IHVuZGVmaW5lZCB8fCBzdGFydCA8IDApIHtcbiAgICBzdGFydCA9IDBcbiAgfVxuICAvLyBSZXR1cm4gZWFybHkgaWYgc3RhcnQgPiB0aGlzLmxlbmd0aC4gRG9uZSBoZXJlIHRvIHByZXZlbnQgcG90ZW50aWFsIHVpbnQzMlxuICAvLyBjb2VyY2lvbiBmYWlsIGJlbG93LlxuICBpZiAoc3RhcnQgPiB0aGlzLmxlbmd0aCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkIHx8IGVuZCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgZW5kID0gdGhpcy5sZW5ndGhcbiAgfVxuXG4gIGlmIChlbmQgPD0gMCkge1xuICAgIHJldHVybiAnJ1xuICB9XG5cbiAgLy8gRm9yY2UgY29lcnNpb24gdG8gdWludDMyLiBUaGlzIHdpbGwgYWxzbyBjb2VyY2UgZmFsc2V5L05hTiB2YWx1ZXMgdG8gMC5cbiAgZW5kID4+Pj0gMFxuICBzdGFydCA+Pj49IDBcblxuICBpZiAoZW5kIDw9IHN0YXJ0KSB7XG4gICAgcmV0dXJuICcnXG4gIH1cblxuICBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9ICd1dGY4J1xuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgc3dpdGNoIChlbmNvZGluZykge1xuICAgICAgY2FzZSAnaGV4JzpcbiAgICAgICAgcmV0dXJuIGhleFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgY2FzZSAndXRmLTgnOlxuICAgICAgICByZXR1cm4gdXRmOFNsaWNlKHRoaXMsIHN0YXJ0LCBlbmQpXG5cbiAgICAgIGNhc2UgJ2FzY2lpJzpcbiAgICAgICAgcmV0dXJuIGFzY2lpU2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiBsYXRpbjFTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBjYXNlICdiYXNlNjQnOlxuICAgICAgICByZXR1cm4gYmFzZTY0U2xpY2UodGhpcywgc3RhcnQsIGVuZClcblxuICAgICAgY2FzZSAndWNzMic6XG4gICAgICBjYXNlICd1Y3MtMic6XG4gICAgICBjYXNlICd1dGYxNmxlJzpcbiAgICAgIGNhc2UgJ3V0Zi0xNmxlJzpcbiAgICAgICAgcmV0dXJuIHV0ZjE2bGVTbGljZSh0aGlzLCBzdGFydCwgZW5kKVxuXG4gICAgICBkZWZhdWx0OlxuICAgICAgICBpZiAobG93ZXJlZENhc2UpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZylcbiAgICAgICAgZW5jb2RpbmcgPSAoZW5jb2RpbmcgKyAnJykudG9Mb3dlckNhc2UoKVxuICAgICAgICBsb3dlcmVkQ2FzZSA9IHRydWVcbiAgICB9XG4gIH1cbn1cblxuLy8gVGhlIHByb3BlcnR5IGlzIHVzZWQgYnkgYEJ1ZmZlci5pc0J1ZmZlcmAgYW5kIGBpcy1idWZmZXJgIChpbiBTYWZhcmkgNS03KSB0byBkZXRlY3Rcbi8vIEJ1ZmZlciBpbnN0YW5jZXMuXG5CdWZmZXIucHJvdG90eXBlLl9pc0J1ZmZlciA9IHRydWVcblxuZnVuY3Rpb24gc3dhcCAoYiwgbiwgbSkge1xuICB2YXIgaSA9IGJbbl1cbiAgYltuXSA9IGJbbV1cbiAgYlttXSA9IGlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zd2FwMTYgPSBmdW5jdGlvbiBzd2FwMTYgKCkge1xuICB2YXIgbGVuID0gdGhpcy5sZW5ndGhcbiAgaWYgKGxlbiAlIDIgIT09IDApIHtcbiAgICB0aHJvdyBuZXcgUmFuZ2VFcnJvcignQnVmZmVyIHNpemUgbXVzdCBiZSBhIG11bHRpcGxlIG9mIDE2LWJpdHMnKVxuICB9XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyBpICs9IDIpIHtcbiAgICBzd2FwKHRoaXMsIGksIGkgKyAxKVxuICB9XG4gIHJldHVybiB0aGlzXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuc3dhcDMyID0gZnVuY3Rpb24gc3dhcDMyICgpIHtcbiAgdmFyIGxlbiA9IHRoaXMubGVuZ3RoXG4gIGlmIChsZW4gJSA0ICE9PSAwKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0J1ZmZlciBzaXplIG11c3QgYmUgYSBtdWx0aXBsZSBvZiAzMi1iaXRzJylcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSArPSA0KSB7XG4gICAgc3dhcCh0aGlzLCBpLCBpICsgMylcbiAgICBzd2FwKHRoaXMsIGkgKyAxLCBpICsgMilcbiAgfVxuICByZXR1cm4gdGhpc1xufVxuXG5CdWZmZXIucHJvdG90eXBlLnN3YXA2NCA9IGZ1bmN0aW9uIHN3YXA2NCAoKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBpZiAobGVuICUgOCAhPT0gMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdCdWZmZXIgc2l6ZSBtdXN0IGJlIGEgbXVsdGlwbGUgb2YgNjQtYml0cycpXG4gIH1cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBsZW47IGkgKz0gOCkge1xuICAgIHN3YXAodGhpcywgaSwgaSArIDcpXG4gICAgc3dhcCh0aGlzLCBpICsgMSwgaSArIDYpXG4gICAgc3dhcCh0aGlzLCBpICsgMiwgaSArIDUpXG4gICAgc3dhcCh0aGlzLCBpICsgMywgaSArIDQpXG4gIH1cbiAgcmV0dXJuIHRoaXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nICgpIHtcbiAgdmFyIGxlbmd0aCA9IHRoaXMubGVuZ3RoIHwgMFxuICBpZiAobGVuZ3RoID09PSAwKSByZXR1cm4gJydcbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApIHJldHVybiB1dGY4U2xpY2UodGhpcywgMCwgbGVuZ3RoKVxuICByZXR1cm4gc2xvd1RvU3RyaW5nLmFwcGx5KHRoaXMsIGFyZ3VtZW50cylcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5lcXVhbHMgPSBmdW5jdGlvbiBlcXVhbHMgKGIpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoYikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBCdWZmZXInKVxuICBpZiAodGhpcyA9PT0gYikgcmV0dXJuIHRydWVcbiAgcmV0dXJuIEJ1ZmZlci5jb21wYXJlKHRoaXMsIGIpID09PSAwXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuaW5zcGVjdCA9IGZ1bmN0aW9uIGluc3BlY3QgKCkge1xuICB2YXIgc3RyID0gJydcbiAgdmFyIG1heCA9IGV4cG9ydHMuSU5TUEVDVF9NQVhfQllURVNcbiAgaWYgKHRoaXMubGVuZ3RoID4gMCkge1xuICAgIHN0ciA9IHRoaXMudG9TdHJpbmcoJ2hleCcsIDAsIG1heCkubWF0Y2goLy57Mn0vZykuam9pbignICcpXG4gICAgaWYgKHRoaXMubGVuZ3RoID4gbWF4KSBzdHIgKz0gJyAuLi4gJ1xuICB9XG4gIHJldHVybiAnPEJ1ZmZlciAnICsgc3RyICsgJz4nXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUuY29tcGFyZSA9IGZ1bmN0aW9uIGNvbXBhcmUgKHRhcmdldCwgc3RhcnQsIGVuZCwgdGhpc1N0YXJ0LCB0aGlzRW5kKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKHRhcmdldCkpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgQnVmZmVyJylcbiAgfVxuXG4gIGlmIChzdGFydCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgc3RhcnQgPSAwXG4gIH1cbiAgaWYgKGVuZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgZW5kID0gdGFyZ2V0ID8gdGFyZ2V0Lmxlbmd0aCA6IDBcbiAgfVxuICBpZiAodGhpc1N0YXJ0ID09PSB1bmRlZmluZWQpIHtcbiAgICB0aGlzU3RhcnQgPSAwXG4gIH1cbiAgaWYgKHRoaXNFbmQgPT09IHVuZGVmaW5lZCkge1xuICAgIHRoaXNFbmQgPSB0aGlzLmxlbmd0aFxuICB9XG5cbiAgaWYgKHN0YXJ0IDwgMCB8fCBlbmQgPiB0YXJnZXQubGVuZ3RoIHx8IHRoaXNTdGFydCA8IDAgfHwgdGhpc0VuZCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ291dCBvZiByYW5nZSBpbmRleCcpXG4gIH1cblxuICBpZiAodGhpc1N0YXJ0ID49IHRoaXNFbmQgJiYgc3RhcnQgPj0gZW5kKSB7XG4gICAgcmV0dXJuIDBcbiAgfVxuICBpZiAodGhpc1N0YXJ0ID49IHRoaXNFbmQpIHtcbiAgICByZXR1cm4gLTFcbiAgfVxuICBpZiAoc3RhcnQgPj0gZW5kKSB7XG4gICAgcmV0dXJuIDFcbiAgfVxuXG4gIHN0YXJ0ID4+Pj0gMFxuICBlbmQgPj4+PSAwXG4gIHRoaXNTdGFydCA+Pj49IDBcbiAgdGhpc0VuZCA+Pj49IDBcblxuICBpZiAodGhpcyA9PT0gdGFyZ2V0KSByZXR1cm4gMFxuXG4gIHZhciB4ID0gdGhpc0VuZCAtIHRoaXNTdGFydFxuICB2YXIgeSA9IGVuZCAtIHN0YXJ0XG4gIHZhciBsZW4gPSBNYXRoLm1pbih4LCB5KVxuXG4gIHZhciB0aGlzQ29weSA9IHRoaXMuc2xpY2UodGhpc1N0YXJ0LCB0aGlzRW5kKVxuICB2YXIgdGFyZ2V0Q29weSA9IHRhcmdldC5zbGljZShzdGFydCwgZW5kKVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICBpZiAodGhpc0NvcHlbaV0gIT09IHRhcmdldENvcHlbaV0pIHtcbiAgICAgIHggPSB0aGlzQ29weVtpXVxuICAgICAgeSA9IHRhcmdldENvcHlbaV1cbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG5cbiAgaWYgKHggPCB5KSByZXR1cm4gLTFcbiAgaWYgKHkgPCB4KSByZXR1cm4gMVxuICByZXR1cm4gMFxufVxuXG4vLyBGaW5kcyBlaXRoZXIgdGhlIGZpcnN0IGluZGV4IG9mIGB2YWxgIGluIGBidWZmZXJgIGF0IG9mZnNldCA+PSBgYnl0ZU9mZnNldGAsXG4vLyBPUiB0aGUgbGFzdCBpbmRleCBvZiBgdmFsYCBpbiBgYnVmZmVyYCBhdCBvZmZzZXQgPD0gYGJ5dGVPZmZzZXRgLlxuLy9cbi8vIEFyZ3VtZW50czpcbi8vIC0gYnVmZmVyIC0gYSBCdWZmZXIgdG8gc2VhcmNoXG4vLyAtIHZhbCAtIGEgc3RyaW5nLCBCdWZmZXIsIG9yIG51bWJlclxuLy8gLSBieXRlT2Zmc2V0IC0gYW4gaW5kZXggaW50byBgYnVmZmVyYDsgd2lsbCBiZSBjbGFtcGVkIHRvIGFuIGludDMyXG4vLyAtIGVuY29kaW5nIC0gYW4gb3B0aW9uYWwgZW5jb2RpbmcsIHJlbGV2YW50IGlzIHZhbCBpcyBhIHN0cmluZ1xuLy8gLSBkaXIgLSB0cnVlIGZvciBpbmRleE9mLCBmYWxzZSBmb3IgbGFzdEluZGV4T2ZcbmZ1bmN0aW9uIGJpZGlyZWN0aW9uYWxJbmRleE9mIChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcsIGRpcikge1xuICAvLyBFbXB0eSBidWZmZXIgbWVhbnMgbm8gbWF0Y2hcbiAgaWYgKGJ1ZmZlci5sZW5ndGggPT09IDApIHJldHVybiAtMVxuXG4gIC8vIE5vcm1hbGl6ZSBieXRlT2Zmc2V0XG4gIGlmICh0eXBlb2YgYnl0ZU9mZnNldCA9PT0gJ3N0cmluZycpIHtcbiAgICBlbmNvZGluZyA9IGJ5dGVPZmZzZXRcbiAgICBieXRlT2Zmc2V0ID0gMFxuICB9IGVsc2UgaWYgKGJ5dGVPZmZzZXQgPiAweDdmZmZmZmZmKSB7XG4gICAgYnl0ZU9mZnNldCA9IDB4N2ZmZmZmZmZcbiAgfSBlbHNlIGlmIChieXRlT2Zmc2V0IDwgLTB4ODAwMDAwMDApIHtcbiAgICBieXRlT2Zmc2V0ID0gLTB4ODAwMDAwMDBcbiAgfVxuICBieXRlT2Zmc2V0ID0gK2J5dGVPZmZzZXQgIC8vIENvZXJjZSB0byBOdW1iZXIuXG4gIGlmIChpc05hTihieXRlT2Zmc2V0KSkge1xuICAgIC8vIGJ5dGVPZmZzZXQ6IGl0IGl0J3MgdW5kZWZpbmVkLCBudWxsLCBOYU4sIFwiZm9vXCIsIGV0Yywgc2VhcmNoIHdob2xlIGJ1ZmZlclxuICAgIGJ5dGVPZmZzZXQgPSBkaXIgPyAwIDogKGJ1ZmZlci5sZW5ndGggLSAxKVxuICB9XG5cbiAgLy8gTm9ybWFsaXplIGJ5dGVPZmZzZXQ6IG5lZ2F0aXZlIG9mZnNldHMgc3RhcnQgZnJvbSB0aGUgZW5kIG9mIHRoZSBidWZmZXJcbiAgaWYgKGJ5dGVPZmZzZXQgPCAwKSBieXRlT2Zmc2V0ID0gYnVmZmVyLmxlbmd0aCArIGJ5dGVPZmZzZXRcbiAgaWYgKGJ5dGVPZmZzZXQgPj0gYnVmZmVyLmxlbmd0aCkge1xuICAgIGlmIChkaXIpIHJldHVybiAtMVxuICAgIGVsc2UgYnl0ZU9mZnNldCA9IGJ1ZmZlci5sZW5ndGggLSAxXG4gIH0gZWxzZSBpZiAoYnl0ZU9mZnNldCA8IDApIHtcbiAgICBpZiAoZGlyKSBieXRlT2Zmc2V0ID0gMFxuICAgIGVsc2UgcmV0dXJuIC0xXG4gIH1cblxuICAvLyBOb3JtYWxpemUgdmFsXG4gIGlmICh0eXBlb2YgdmFsID09PSAnc3RyaW5nJykge1xuICAgIHZhbCA9IEJ1ZmZlci5mcm9tKHZhbCwgZW5jb2RpbmcpXG4gIH1cblxuICAvLyBGaW5hbGx5LCBzZWFyY2ggZWl0aGVyIGluZGV4T2YgKGlmIGRpciBpcyB0cnVlKSBvciBsYXN0SW5kZXhPZlxuICBpZiAoQnVmZmVyLmlzQnVmZmVyKHZhbCkpIHtcbiAgICAvLyBTcGVjaWFsIGNhc2U6IGxvb2tpbmcgZm9yIGVtcHR5IHN0cmluZy9idWZmZXIgYWx3YXlzIGZhaWxzXG4gICAgaWYgKHZhbC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiAtMVxuICAgIH1cbiAgICByZXR1cm4gYXJyYXlJbmRleE9mKGJ1ZmZlciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKVxuICB9IGVsc2UgaWYgKHR5cGVvZiB2YWwgPT09ICdudW1iZXInKSB7XG4gICAgdmFsID0gdmFsICYgMHhGRiAvLyBTZWFyY2ggZm9yIGEgYnl0ZSB2YWx1ZSBbMC0yNTVdXG4gICAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUICYmXG4gICAgICAgIHR5cGVvZiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBpZiAoZGlyKSB7XG4gICAgICAgIHJldHVybiBVaW50OEFycmF5LnByb3RvdHlwZS5pbmRleE9mLmNhbGwoYnVmZmVyLCB2YWwsIGJ5dGVPZmZzZXQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gVWludDhBcnJheS5wcm90b3R5cGUubGFzdEluZGV4T2YuY2FsbChidWZmZXIsIHZhbCwgYnl0ZU9mZnNldClcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGFycmF5SW5kZXhPZihidWZmZXIsIFsgdmFsIF0sIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBkaXIpXG4gIH1cblxuICB0aHJvdyBuZXcgVHlwZUVycm9yKCd2YWwgbXVzdCBiZSBzdHJpbmcsIG51bWJlciBvciBCdWZmZXInKVxufVxuXG5mdW5jdGlvbiBhcnJheUluZGV4T2YgKGFyciwgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgZGlyKSB7XG4gIHZhciBpbmRleFNpemUgPSAxXG4gIHZhciBhcnJMZW5ndGggPSBhcnIubGVuZ3RoXG4gIHZhciB2YWxMZW5ndGggPSB2YWwubGVuZ3RoXG5cbiAgaWYgKGVuY29kaW5nICE9PSB1bmRlZmluZWQpIHtcbiAgICBlbmNvZGluZyA9IFN0cmluZyhlbmNvZGluZykudG9Mb3dlckNhc2UoKVxuICAgIGlmIChlbmNvZGluZyA9PT0gJ3VjczInIHx8IGVuY29kaW5nID09PSAndWNzLTInIHx8XG4gICAgICAgIGVuY29kaW5nID09PSAndXRmMTZsZScgfHwgZW5jb2RpbmcgPT09ICd1dGYtMTZsZScpIHtcbiAgICAgIGlmIChhcnIubGVuZ3RoIDwgMiB8fCB2YWwubGVuZ3RoIDwgMikge1xuICAgICAgICByZXR1cm4gLTFcbiAgICAgIH1cbiAgICAgIGluZGV4U2l6ZSA9IDJcbiAgICAgIGFyckxlbmd0aCAvPSAyXG4gICAgICB2YWxMZW5ndGggLz0gMlxuICAgICAgYnl0ZU9mZnNldCAvPSAyXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gcmVhZCAoYnVmLCBpKSB7XG4gICAgaWYgKGluZGV4U2l6ZSA9PT0gMSkge1xuICAgICAgcmV0dXJuIGJ1ZltpXVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gYnVmLnJlYWRVSW50MTZCRShpICogaW5kZXhTaXplKVxuICAgIH1cbiAgfVxuXG4gIHZhciBpXG4gIGlmIChkaXIpIHtcbiAgICB2YXIgZm91bmRJbmRleCA9IC0xXG4gICAgZm9yIChpID0gYnl0ZU9mZnNldDsgaSA8IGFyckxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAocmVhZChhcnIsIGkpID09PSByZWFkKHZhbCwgZm91bmRJbmRleCA9PT0gLTEgPyAwIDogaSAtIGZvdW5kSW5kZXgpKSB7XG4gICAgICAgIGlmIChmb3VuZEluZGV4ID09PSAtMSkgZm91bmRJbmRleCA9IGlcbiAgICAgICAgaWYgKGkgLSBmb3VuZEluZGV4ICsgMSA9PT0gdmFsTGVuZ3RoKSByZXR1cm4gZm91bmRJbmRleCAqIGluZGV4U2l6ZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgaWYgKGZvdW5kSW5kZXggIT09IC0xKSBpIC09IGkgLSBmb3VuZEluZGV4XG4gICAgICAgIGZvdW5kSW5kZXggPSAtMVxuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBpZiAoYnl0ZU9mZnNldCArIHZhbExlbmd0aCA+IGFyckxlbmd0aCkgYnl0ZU9mZnNldCA9IGFyckxlbmd0aCAtIHZhbExlbmd0aFxuICAgIGZvciAoaSA9IGJ5dGVPZmZzZXQ7IGkgPj0gMDsgaS0tKSB7XG4gICAgICB2YXIgZm91bmQgPSB0cnVlXG4gICAgICBmb3IgKHZhciBqID0gMDsgaiA8IHZhbExlbmd0aDsgaisrKSB7XG4gICAgICAgIGlmIChyZWFkKGFyciwgaSArIGopICE9PSByZWFkKHZhbCwgaikpIHtcbiAgICAgICAgICBmb3VuZCA9IGZhbHNlXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKGZvdW5kKSByZXR1cm4gaVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiAtMVxufVxuXG5CdWZmZXIucHJvdG90eXBlLmluY2x1ZGVzID0gZnVuY3Rpb24gaW5jbHVkZXMgKHZhbCwgYnl0ZU9mZnNldCwgZW5jb2RpbmcpIHtcbiAgcmV0dXJuIHRoaXMuaW5kZXhPZih2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSAhPT0gLTFcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5pbmRleE9mID0gZnVuY3Rpb24gaW5kZXhPZiAodmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZykge1xuICByZXR1cm4gYmlkaXJlY3Rpb25hbEluZGV4T2YodGhpcywgdmFsLCBieXRlT2Zmc2V0LCBlbmNvZGluZywgdHJ1ZSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5sYXN0SW5kZXhPZiA9IGZ1bmN0aW9uIGxhc3RJbmRleE9mICh2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nKSB7XG4gIHJldHVybiBiaWRpcmVjdGlvbmFsSW5kZXhPZih0aGlzLCB2YWwsIGJ5dGVPZmZzZXQsIGVuY29kaW5nLCBmYWxzZSlcbn1cblxuZnVuY3Rpb24gaGV4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICBvZmZzZXQgPSBOdW1iZXIob2Zmc2V0KSB8fCAwXG4gIHZhciByZW1haW5pbmcgPSBidWYubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmICghbGVuZ3RoKSB7XG4gICAgbGVuZ3RoID0gcmVtYWluaW5nXG4gIH0gZWxzZSB7XG4gICAgbGVuZ3RoID0gTnVtYmVyKGxlbmd0aClcbiAgICBpZiAobGVuZ3RoID4gcmVtYWluaW5nKSB7XG4gICAgICBsZW5ndGggPSByZW1haW5pbmdcbiAgICB9XG4gIH1cblxuICAvLyBtdXN0IGJlIGFuIGV2ZW4gbnVtYmVyIG9mIGRpZ2l0c1xuICB2YXIgc3RyTGVuID0gc3RyaW5nLmxlbmd0aFxuICBpZiAoc3RyTGVuICUgMiAhPT0gMCkgdGhyb3cgbmV3IFR5cGVFcnJvcignSW52YWxpZCBoZXggc3RyaW5nJylcblxuICBpZiAobGVuZ3RoID4gc3RyTGVuIC8gMikge1xuICAgIGxlbmd0aCA9IHN0ckxlbiAvIDJcbiAgfVxuICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbmd0aDsgKytpKSB7XG4gICAgdmFyIHBhcnNlZCA9IHBhcnNlSW50KHN0cmluZy5zdWJzdHIoaSAqIDIsIDIpLCAxNilcbiAgICBpZiAoaXNOYU4ocGFyc2VkKSkgcmV0dXJuIGlcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSBwYXJzZWRcbiAgfVxuICByZXR1cm4gaVxufVxuXG5mdW5jdGlvbiB1dGY4V3JpdGUgKGJ1Ziwgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aCkge1xuICByZXR1cm4gYmxpdEJ1ZmZlcih1dGY4VG9CeXRlcyhzdHJpbmcsIGJ1Zi5sZW5ndGggLSBvZmZzZXQpLCBidWYsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBhc2NpaVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIoYXNjaWlUb0J5dGVzKHN0cmluZyksIGJ1Ziwgb2Zmc2V0LCBsZW5ndGgpXG59XG5cbmZ1bmN0aW9uIGxhdGluMVdyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGFzY2lpV3JpdGUoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxufVxuXG5mdW5jdGlvbiBiYXNlNjRXcml0ZSAoYnVmLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBibGl0QnVmZmVyKGJhc2U2NFRvQnl0ZXMoc3RyaW5nKSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuZnVuY3Rpb24gdWNzMldyaXRlIChidWYsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpIHtcbiAgcmV0dXJuIGJsaXRCdWZmZXIodXRmMTZsZVRvQnl0ZXMoc3RyaW5nLCBidWYubGVuZ3RoIC0gb2Zmc2V0KSwgYnVmLCBvZmZzZXQsIGxlbmd0aClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uIHdyaXRlIChzdHJpbmcsIG9mZnNldCwgbGVuZ3RoLCBlbmNvZGluZykge1xuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nKVxuICBpZiAob2Zmc2V0ID09PSB1bmRlZmluZWQpIHtcbiAgICBlbmNvZGluZyA9ICd1dGY4J1xuICAgIGxlbmd0aCA9IHRoaXMubGVuZ3RoXG4gICAgb2Zmc2V0ID0gMFxuICAvLyBCdWZmZXIjd3JpdGUoc3RyaW5nLCBlbmNvZGluZylcbiAgfSBlbHNlIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCAmJiB0eXBlb2Ygb2Zmc2V0ID09PSAnc3RyaW5nJykge1xuICAgIGVuY29kaW5nID0gb2Zmc2V0XG4gICAgbGVuZ3RoID0gdGhpcy5sZW5ndGhcbiAgICBvZmZzZXQgPSAwXG4gIC8vIEJ1ZmZlciN3cml0ZShzdHJpbmcsIG9mZnNldFssIGxlbmd0aF1bLCBlbmNvZGluZ10pXG4gIH0gZWxzZSBpZiAoaXNGaW5pdGUob2Zmc2V0KSkge1xuICAgIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgICBpZiAoaXNGaW5pdGUobGVuZ3RoKSkge1xuICAgICAgbGVuZ3RoID0gbGVuZ3RoIHwgMFxuICAgICAgaWYgKGVuY29kaW5nID09PSB1bmRlZmluZWQpIGVuY29kaW5nID0gJ3V0ZjgnXG4gICAgfSBlbHNlIHtcbiAgICAgIGVuY29kaW5nID0gbGVuZ3RoXG4gICAgICBsZW5ndGggPSB1bmRlZmluZWRcbiAgICB9XG4gIC8vIGxlZ2FjeSB3cml0ZShzdHJpbmcsIGVuY29kaW5nLCBvZmZzZXQsIGxlbmd0aCkgLSByZW1vdmUgaW4gdjAuMTNcbiAgfSBlbHNlIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAnQnVmZmVyLndyaXRlKHN0cmluZywgZW5jb2RpbmcsIG9mZnNldFssIGxlbmd0aF0pIGlzIG5vIGxvbmdlciBzdXBwb3J0ZWQnXG4gICAgKVxuICB9XG5cbiAgdmFyIHJlbWFpbmluZyA9IHRoaXMubGVuZ3RoIC0gb2Zmc2V0XG4gIGlmIChsZW5ndGggPT09IHVuZGVmaW5lZCB8fCBsZW5ndGggPiByZW1haW5pbmcpIGxlbmd0aCA9IHJlbWFpbmluZ1xuXG4gIGlmICgoc3RyaW5nLmxlbmd0aCA+IDAgJiYgKGxlbmd0aCA8IDAgfHwgb2Zmc2V0IDwgMCkpIHx8IG9mZnNldCA+IHRoaXMubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ0F0dGVtcHQgdG8gd3JpdGUgb3V0c2lkZSBidWZmZXIgYm91bmRzJylcbiAgfVxuXG4gIGlmICghZW5jb2RpbmcpIGVuY29kaW5nID0gJ3V0ZjgnXG5cbiAgdmFyIGxvd2VyZWRDYXNlID0gZmFsc2VcbiAgZm9yICg7Oykge1xuICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcbiAgICAgIGNhc2UgJ2hleCc6XG4gICAgICAgIHJldHVybiBoZXhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICd1dGY4JzpcbiAgICAgIGNhc2UgJ3V0Zi04JzpcbiAgICAgICAgcmV0dXJuIHV0ZjhXcml0ZSh0aGlzLCBzdHJpbmcsIG9mZnNldCwgbGVuZ3RoKVxuXG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICAgIHJldHVybiBhc2NpaVdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ2xhdGluMSc6XG4gICAgICBjYXNlICdiaW5hcnknOlxuICAgICAgICByZXR1cm4gbGF0aW4xV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgY2FzZSAnYmFzZTY0JzpcbiAgICAgICAgLy8gV2FybmluZzogbWF4TGVuZ3RoIG5vdCB0YWtlbiBpbnRvIGFjY291bnQgaW4gYmFzZTY0V3JpdGVcbiAgICAgICAgcmV0dXJuIGJhc2U2NFdyaXRlKHRoaXMsIHN0cmluZywgb2Zmc2V0LCBsZW5ndGgpXG5cbiAgICAgIGNhc2UgJ3VjczInOlxuICAgICAgY2FzZSAndWNzLTInOlxuICAgICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICBjYXNlICd1dGYtMTZsZSc6XG4gICAgICAgIHJldHVybiB1Y3MyV3JpdGUodGhpcywgc3RyaW5nLCBvZmZzZXQsIGxlbmd0aClcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKGxvd2VyZWRDYXNlKSB0aHJvdyBuZXcgVHlwZUVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jb2RpbmcpXG4gICAgICAgIGVuY29kaW5nID0gKCcnICsgZW5jb2RpbmcpLnRvTG93ZXJDYXNlKClcbiAgICAgICAgbG93ZXJlZENhc2UgPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUudG9KU09OID0gZnVuY3Rpb24gdG9KU09OICgpIHtcbiAgcmV0dXJuIHtcbiAgICB0eXBlOiAnQnVmZmVyJyxcbiAgICBkYXRhOiBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbCh0aGlzLl9hcnIgfHwgdGhpcywgMClcbiAgfVxufVxuXG5mdW5jdGlvbiBiYXNlNjRTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIGlmIChzdGFydCA9PT0gMCAmJiBlbmQgPT09IGJ1Zi5sZW5ndGgpIHtcbiAgICByZXR1cm4gYmFzZTY0LmZyb21CeXRlQXJyYXkoYnVmKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBiYXNlNjQuZnJvbUJ5dGVBcnJheShidWYuc2xpY2Uoc3RhcnQsIGVuZCkpXG4gIH1cbn1cblxuZnVuY3Rpb24gdXRmOFNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgZW5kID0gTWF0aC5taW4oYnVmLmxlbmd0aCwgZW5kKVxuICB2YXIgcmVzID0gW11cblxuICB2YXIgaSA9IHN0YXJ0XG4gIHdoaWxlIChpIDwgZW5kKSB7XG4gICAgdmFyIGZpcnN0Qnl0ZSA9IGJ1ZltpXVxuICAgIHZhciBjb2RlUG9pbnQgPSBudWxsXG4gICAgdmFyIGJ5dGVzUGVyU2VxdWVuY2UgPSAoZmlyc3RCeXRlID4gMHhFRikgPyA0XG4gICAgICA6IChmaXJzdEJ5dGUgPiAweERGKSA/IDNcbiAgICAgIDogKGZpcnN0Qnl0ZSA+IDB4QkYpID8gMlxuICAgICAgOiAxXG5cbiAgICBpZiAoaSArIGJ5dGVzUGVyU2VxdWVuY2UgPD0gZW5kKSB7XG4gICAgICB2YXIgc2Vjb25kQnl0ZSwgdGhpcmRCeXRlLCBmb3VydGhCeXRlLCB0ZW1wQ29kZVBvaW50XG5cbiAgICAgIHN3aXRjaCAoYnl0ZXNQZXJTZXF1ZW5jZSkge1xuICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgaWYgKGZpcnN0Qnl0ZSA8IDB4ODApIHtcbiAgICAgICAgICAgIGNvZGVQb2ludCA9IGZpcnN0Qnl0ZVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweDFGKSA8PCAweDYgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4N0YpIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICB0aGlyZEJ5dGUgPSBidWZbaSArIDJdXG4gICAgICAgICAgaWYgKChzZWNvbmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKHRoaXJkQnl0ZSAmIDB4QzApID09PSAweDgwKSB7XG4gICAgICAgICAgICB0ZW1wQ29kZVBvaW50ID0gKGZpcnN0Qnl0ZSAmIDB4RikgPDwgMHhDIHwgKHNlY29uZEJ5dGUgJiAweDNGKSA8PCAweDYgfCAodGhpcmRCeXRlICYgMHgzRilcbiAgICAgICAgICAgIGlmICh0ZW1wQ29kZVBvaW50ID4gMHg3RkYgJiYgKHRlbXBDb2RlUG9pbnQgPCAweEQ4MDAgfHwgdGVtcENvZGVQb2ludCA+IDB4REZGRikpIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBicmVha1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgc2Vjb25kQnl0ZSA9IGJ1ZltpICsgMV1cbiAgICAgICAgICB0aGlyZEJ5dGUgPSBidWZbaSArIDJdXG4gICAgICAgICAgZm91cnRoQnl0ZSA9IGJ1ZltpICsgM11cbiAgICAgICAgICBpZiAoKHNlY29uZEJ5dGUgJiAweEMwKSA9PT0gMHg4MCAmJiAodGhpcmRCeXRlICYgMHhDMCkgPT09IDB4ODAgJiYgKGZvdXJ0aEJ5dGUgJiAweEMwKSA9PT0gMHg4MCkge1xuICAgICAgICAgICAgdGVtcENvZGVQb2ludCA9IChmaXJzdEJ5dGUgJiAweEYpIDw8IDB4MTIgfCAoc2Vjb25kQnl0ZSAmIDB4M0YpIDw8IDB4QyB8ICh0aGlyZEJ5dGUgJiAweDNGKSA8PCAweDYgfCAoZm91cnRoQnl0ZSAmIDB4M0YpXG4gICAgICAgICAgICBpZiAodGVtcENvZGVQb2ludCA+IDB4RkZGRiAmJiB0ZW1wQ29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgICAgICAgICAgY29kZVBvaW50ID0gdGVtcENvZGVQb2ludFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoY29kZVBvaW50ID09PSBudWxsKSB7XG4gICAgICAvLyB3ZSBkaWQgbm90IGdlbmVyYXRlIGEgdmFsaWQgY29kZVBvaW50IHNvIGluc2VydCBhXG4gICAgICAvLyByZXBsYWNlbWVudCBjaGFyIChVK0ZGRkQpIGFuZCBhZHZhbmNlIG9ubHkgMSBieXRlXG4gICAgICBjb2RlUG9pbnQgPSAweEZGRkRcbiAgICAgIGJ5dGVzUGVyU2VxdWVuY2UgPSAxXG4gICAgfSBlbHNlIGlmIChjb2RlUG9pbnQgPiAweEZGRkYpIHtcbiAgICAgIC8vIGVuY29kZSB0byB1dGYxNiAoc3Vycm9nYXRlIHBhaXIgZGFuY2UpXG4gICAgICBjb2RlUG9pbnQgLT0gMHgxMDAwMFxuICAgICAgcmVzLnB1c2goY29kZVBvaW50ID4+PiAxMCAmIDB4M0ZGIHwgMHhEODAwKVxuICAgICAgY29kZVBvaW50ID0gMHhEQzAwIHwgY29kZVBvaW50ICYgMHgzRkZcbiAgICB9XG5cbiAgICByZXMucHVzaChjb2RlUG9pbnQpXG4gICAgaSArPSBieXRlc1BlclNlcXVlbmNlXG4gIH1cblxuICByZXR1cm4gZGVjb2RlQ29kZVBvaW50c0FycmF5KHJlcylcbn1cblxuLy8gQmFzZWQgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMjI3NDcyNzIvNjgwNzQyLCB0aGUgYnJvd3NlciB3aXRoXG4vLyB0aGUgbG93ZXN0IGxpbWl0IGlzIENocm9tZSwgd2l0aCAweDEwMDAwIGFyZ3MuXG4vLyBXZSBnbyAxIG1hZ25pdHVkZSBsZXNzLCBmb3Igc2FmZXR5XG52YXIgTUFYX0FSR1VNRU5UU19MRU5HVEggPSAweDEwMDBcblxuZnVuY3Rpb24gZGVjb2RlQ29kZVBvaW50c0FycmF5IChjb2RlUG9pbnRzKSB7XG4gIHZhciBsZW4gPSBjb2RlUG9pbnRzLmxlbmd0aFxuICBpZiAobGVuIDw9IE1BWF9BUkdVTUVOVFNfTEVOR1RIKSB7XG4gICAgcmV0dXJuIFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjb2RlUG9pbnRzKSAvLyBhdm9pZCBleHRyYSBzbGljZSgpXG4gIH1cblxuICAvLyBEZWNvZGUgaW4gY2h1bmtzIHRvIGF2b2lkIFwiY2FsbCBzdGFjayBzaXplIGV4Y2VlZGVkXCIuXG4gIHZhciByZXMgPSAnJ1xuICB2YXIgaSA9IDBcbiAgd2hpbGUgKGkgPCBsZW4pIHtcbiAgICByZXMgKz0gU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShcbiAgICAgIFN0cmluZyxcbiAgICAgIGNvZGVQb2ludHMuc2xpY2UoaSwgaSArPSBNQVhfQVJHVU1FTlRTX0xFTkdUSClcbiAgICApXG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVNsaWNlIChidWYsIHN0YXJ0LCBlbmQpIHtcbiAgdmFyIHJldCA9ICcnXG4gIGVuZCA9IE1hdGgubWluKGJ1Zi5sZW5ndGgsIGVuZClcblxuICBmb3IgKHZhciBpID0gc3RhcnQ7IGkgPCBlbmQ7ICsraSkge1xuICAgIHJldCArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ1ZltpXSAmIDB4N0YpXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBsYXRpbjFTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciByZXQgPSAnJ1xuICBlbmQgPSBNYXRoLm1pbihidWYubGVuZ3RoLCBlbmQpXG5cbiAgZm9yICh2YXIgaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICByZXQgKz0gU3RyaW5nLmZyb21DaGFyQ29kZShidWZbaV0pXG4gIH1cbiAgcmV0dXJuIHJldFxufVxuXG5mdW5jdGlvbiBoZXhTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSBidWYubGVuZ3RoXG5cbiAgaWYgKCFzdGFydCB8fCBzdGFydCA8IDApIHN0YXJ0ID0gMFxuICBpZiAoIWVuZCB8fCBlbmQgPCAwIHx8IGVuZCA+IGxlbikgZW5kID0gbGVuXG5cbiAgdmFyIG91dCA9ICcnXG4gIGZvciAodmFyIGkgPSBzdGFydDsgaSA8IGVuZDsgKytpKSB7XG4gICAgb3V0ICs9IHRvSGV4KGJ1ZltpXSlcbiAgfVxuICByZXR1cm4gb3V0XG59XG5cbmZ1bmN0aW9uIHV0ZjE2bGVTbGljZSAoYnVmLCBzdGFydCwgZW5kKSB7XG4gIHZhciBieXRlcyA9IGJ1Zi5zbGljZShzdGFydCwgZW5kKVxuICB2YXIgcmVzID0gJydcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBieXRlcy5sZW5ndGg7IGkgKz0gMikge1xuICAgIHJlcyArPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGJ5dGVzW2ldICsgYnl0ZXNbaSArIDFdICogMjU2KVxuICB9XG4gIHJldHVybiByZXNcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uIHNsaWNlIChzdGFydCwgZW5kKSB7XG4gIHZhciBsZW4gPSB0aGlzLmxlbmd0aFxuICBzdGFydCA9IH5+c3RhcnRcbiAgZW5kID0gZW5kID09PSB1bmRlZmluZWQgPyBsZW4gOiB+fmVuZFxuXG4gIGlmIChzdGFydCA8IDApIHtcbiAgICBzdGFydCArPSBsZW5cbiAgICBpZiAoc3RhcnQgPCAwKSBzdGFydCA9IDBcbiAgfSBlbHNlIGlmIChzdGFydCA+IGxlbikge1xuICAgIHN0YXJ0ID0gbGVuXG4gIH1cblxuICBpZiAoZW5kIDwgMCkge1xuICAgIGVuZCArPSBsZW5cbiAgICBpZiAoZW5kIDwgMCkgZW5kID0gMFxuICB9IGVsc2UgaWYgKGVuZCA+IGxlbikge1xuICAgIGVuZCA9IGxlblxuICB9XG5cbiAgaWYgKGVuZCA8IHN0YXJ0KSBlbmQgPSBzdGFydFxuXG4gIHZhciBuZXdCdWZcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgbmV3QnVmID0gdGhpcy5zdWJhcnJheShzdGFydCwgZW5kKVxuICAgIG5ld0J1Zi5fX3Byb3RvX18gPSBCdWZmZXIucHJvdG90eXBlXG4gIH0gZWxzZSB7XG4gICAgdmFyIHNsaWNlTGVuID0gZW5kIC0gc3RhcnRcbiAgICBuZXdCdWYgPSBuZXcgQnVmZmVyKHNsaWNlTGVuLCB1bmRlZmluZWQpXG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzbGljZUxlbjsgKytpKSB7XG4gICAgICBuZXdCdWZbaV0gPSB0aGlzW2kgKyBzdGFydF1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmV3QnVmXG59XG5cbi8qXG4gKiBOZWVkIHRvIG1ha2Ugc3VyZSB0aGF0IGJ1ZmZlciBpc24ndCB0cnlpbmcgdG8gd3JpdGUgb3V0IG9mIGJvdW5kcy5cbiAqL1xuZnVuY3Rpb24gY2hlY2tPZmZzZXQgKG9mZnNldCwgZXh0LCBsZW5ndGgpIHtcbiAgaWYgKChvZmZzZXQgJSAxKSAhPT0gMCB8fCBvZmZzZXQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignb2Zmc2V0IGlzIG5vdCB1aW50JylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGxlbmd0aCkgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1RyeWluZyB0byBhY2Nlc3MgYmV5b25kIGJ1ZmZlciBsZW5ndGgnKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50TEUgPSBmdW5jdGlvbiByZWFkVUludExFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgYnl0ZUxlbmd0aCwgdGhpcy5sZW5ndGgpXG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0XVxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgd2hpbGUgKCsraSA8IGJ5dGVMZW5ndGggJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyBpXSAqIG11bFxuICB9XG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50QkUgPSBmdW5jdGlvbiByZWFkVUludEJFIChvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuICB9XG5cbiAgdmFyIHZhbCA9IHRoaXNbb2Zmc2V0ICsgLS1ieXRlTGVuZ3RoXVxuICB2YXIgbXVsID0gMVxuICB3aGlsZSAoYnl0ZUxlbmd0aCA+IDAgJiYgKG11bCAqPSAweDEwMCkpIHtcbiAgICB2YWwgKz0gdGhpc1tvZmZzZXQgKyAtLWJ5dGVMZW5ndGhdICogbXVsXG4gIH1cblxuICByZXR1cm4gdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQ4ID0gZnVuY3Rpb24gcmVhZFVJbnQ4IChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMSwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiB0aGlzW29mZnNldF1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDE2TEUgPSBmdW5jdGlvbiByZWFkVUludDE2TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAyLCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIHRoaXNbb2Zmc2V0XSB8ICh0aGlzW29mZnNldCArIDFdIDw8IDgpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZFVJbnQxNkJFID0gZnVuY3Rpb24gcmVhZFVJbnQxNkJFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHJldHVybiAodGhpc1tvZmZzZXRdIDw8IDgpIHwgdGhpc1tvZmZzZXQgKyAxXVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRVSW50MzJMRSA9IGZ1bmN0aW9uIHJlYWRVSW50MzJMRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDQsIHRoaXMubGVuZ3RoKVxuXG4gIHJldHVybiAoKHRoaXNbb2Zmc2V0XSkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMV0gPDwgOCkgfFxuICAgICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgMTYpKSArXG4gICAgICAodGhpc1tvZmZzZXQgKyAzXSAqIDB4MTAwMDAwMClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkVUludDMyQkUgPSBmdW5jdGlvbiByZWFkVUludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSAqIDB4MTAwMDAwMCkgK1xuICAgICgodGhpc1tvZmZzZXQgKyAxXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDJdIDw8IDgpIHxcbiAgICB0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRMRSA9IGZ1bmN0aW9uIHJlYWRJbnRMRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF1cbiAgdmFyIG11bCA9IDFcbiAgdmFyIGkgPSAwXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdmFsICs9IHRoaXNbb2Zmc2V0ICsgaV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnRCRSA9IGZ1bmN0aW9uIHJlYWRJbnRCRSAob2Zmc2V0LCBieXRlTGVuZ3RoLCBub0Fzc2VydCkge1xuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGJ5dGVMZW5ndGggPSBieXRlTGVuZ3RoIHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIGJ5dGVMZW5ndGgsIHRoaXMubGVuZ3RoKVxuXG4gIHZhciBpID0gYnl0ZUxlbmd0aFxuICB2YXIgbXVsID0gMVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAtLWldXG4gIHdoaWxlIChpID4gMCAmJiAobXVsICo9IDB4MTAwKSkge1xuICAgIHZhbCArPSB0aGlzW29mZnNldCArIC0taV0gKiBtdWxcbiAgfVxuICBtdWwgKj0gMHg4MFxuXG4gIGlmICh2YWwgPj0gbXVsKSB2YWwgLT0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGgpXG5cbiAgcmV0dXJuIHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQ4ID0gZnVuY3Rpb24gcmVhZEludDggKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCAxLCB0aGlzLmxlbmd0aClcbiAgaWYgKCEodGhpc1tvZmZzZXRdICYgMHg4MCkpIHJldHVybiAodGhpc1tvZmZzZXRdKVxuICByZXR1cm4gKCgweGZmIC0gdGhpc1tvZmZzZXRdICsgMSkgKiAtMSlcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkSW50MTZMRSA9IGZ1bmN0aW9uIHJlYWRJbnQxNkxFIChvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrT2Zmc2V0KG9mZnNldCwgMiwgdGhpcy5sZW5ndGgpXG4gIHZhciB2YWwgPSB0aGlzW29mZnNldF0gfCAodGhpc1tvZmZzZXQgKyAxXSA8PCA4KVxuICByZXR1cm4gKHZhbCAmIDB4ODAwMCkgPyB2YWwgfCAweEZGRkYwMDAwIDogdmFsXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUucmVhZEludDE2QkUgPSBmdW5jdGlvbiByZWFkSW50MTZCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDIsIHRoaXMubGVuZ3RoKVxuICB2YXIgdmFsID0gdGhpc1tvZmZzZXQgKyAxXSB8ICh0aGlzW29mZnNldF0gPDwgOClcbiAgcmV0dXJuICh2YWwgJiAweDgwMDApID8gdmFsIHwgMHhGRkZGMDAwMCA6IHZhbFxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkxFID0gZnVuY3Rpb24gcmVhZEludDMyTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDgpIHxcbiAgICAodGhpc1tvZmZzZXQgKyAyXSA8PCAxNikgfFxuICAgICh0aGlzW29mZnNldCArIDNdIDw8IDI0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRJbnQzMkJFID0gZnVuY3Rpb24gcmVhZEludDMyQkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcblxuICByZXR1cm4gKHRoaXNbb2Zmc2V0XSA8PCAyNCkgfFxuICAgICh0aGlzW29mZnNldCArIDFdIDw8IDE2KSB8XG4gICAgKHRoaXNbb2Zmc2V0ICsgMl0gPDwgOCkgfFxuICAgICh0aGlzW29mZnNldCArIDNdKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdExFID0gZnVuY3Rpb24gcmVhZEZsb2F0TEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDIzLCA0KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWRGbG9hdEJFID0gZnVuY3Rpb24gcmVhZEZsb2F0QkUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA0LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIGZhbHNlLCAyMywgNClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS5yZWFkRG91YmxlTEUgPSBmdW5jdGlvbiByZWFkRG91YmxlTEUgKG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tPZmZzZXQob2Zmc2V0LCA4LCB0aGlzLmxlbmd0aClcbiAgcmV0dXJuIGllZWU3NTQucmVhZCh0aGlzLCBvZmZzZXQsIHRydWUsIDUyLCA4KVxufVxuXG5CdWZmZXIucHJvdG90eXBlLnJlYWREb3VibGVCRSA9IGZ1bmN0aW9uIHJlYWREb3VibGVCRSAob2Zmc2V0LCBub0Fzc2VydCkge1xuICBpZiAoIW5vQXNzZXJ0KSBjaGVja09mZnNldChvZmZzZXQsIDgsIHRoaXMubGVuZ3RoKVxuICByZXR1cm4gaWVlZTc1NC5yZWFkKHRoaXMsIG9mZnNldCwgZmFsc2UsIDUyLCA4KVxufVxuXG5mdW5jdGlvbiBjaGVja0ludCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmICghQnVmZmVyLmlzQnVmZmVyKGJ1ZikpIHRocm93IG5ldyBUeXBlRXJyb3IoJ1wiYnVmZmVyXCIgYXJndW1lbnQgbXVzdCBiZSBhIEJ1ZmZlciBpbnN0YW5jZScpXG4gIGlmICh2YWx1ZSA+IG1heCB8fCB2YWx1ZSA8IG1pbikgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1widmFsdWVcIiBhcmd1bWVudCBpcyBvdXQgb2YgYm91bmRzJylcbiAgaWYgKG9mZnNldCArIGV4dCA+IGJ1Zi5sZW5ndGgpIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludExFID0gZnVuY3Rpb24gd3JpdGVVSW50TEUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbWF4Qnl0ZXMgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCkgLSAxXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbWF4Qnl0ZXMsIDApXG4gIH1cblxuICB2YXIgbXVsID0gMVxuICB2YXIgaSA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludEJFID0gZnVuY3Rpb24gd3JpdGVVSW50QkUgKHZhbHVlLCBvZmZzZXQsIGJ5dGVMZW5ndGgsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgYnl0ZUxlbmd0aCA9IGJ5dGVMZW5ndGggfCAwXG4gIGlmICghbm9Bc3NlcnQpIHtcbiAgICB2YXIgbWF4Qnl0ZXMgPSBNYXRoLnBvdygyLCA4ICogYnl0ZUxlbmd0aCkgLSAxXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbWF4Qnl0ZXMsIDApXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICh2YWx1ZSAvIG11bCkgJiAweEZGXG4gIH1cblxuICByZXR1cm4gb2Zmc2V0ICsgYnl0ZUxlbmd0aFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlVUludDggPSBmdW5jdGlvbiB3cml0ZVVJbnQ4ICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDEsIDB4ZmYsIDApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSlcbiAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgcmV0dXJuIG9mZnNldCArIDFcbn1cblxuZnVuY3Rpb24gb2JqZWN0V3JpdGVVSW50MTYgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuKSB7XG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZmZmICsgdmFsdWUgKyAxXG4gIGZvciAodmFyIGkgPSAwLCBqID0gTWF0aC5taW4oYnVmLmxlbmd0aCAtIG9mZnNldCwgMik7IGkgPCBqOyArK2kpIHtcbiAgICBidWZbb2Zmc2V0ICsgaV0gPSAodmFsdWUgJiAoMHhmZiA8PCAoOCAqIChsaXR0bGVFbmRpYW4gPyBpIDogMSAtIGkpKSkpID4+PlxuICAgICAgKGxpdHRsZUVuZGlhbiA/IGkgOiAxIC0gaSkgKiA4XG4gIH1cbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVVSW50MTZMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCAyLCAweGZmZmYsIDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQxNih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyAyXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MTZCRSA9IGZ1bmN0aW9uIHdyaXRlVUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHhmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuZnVuY3Rpb24gb2JqZWN0V3JpdGVVSW50MzIgKGJ1ZiwgdmFsdWUsIG9mZnNldCwgbGl0dGxlRW5kaWFuKSB7XG4gIGlmICh2YWx1ZSA8IDApIHZhbHVlID0gMHhmZmZmZmZmZiArIHZhbHVlICsgMVxuICBmb3IgKHZhciBpID0gMCwgaiA9IE1hdGgubWluKGJ1Zi5sZW5ndGggLSBvZmZzZXQsIDQpOyBpIDwgajsgKytpKSB7XG4gICAgYnVmW29mZnNldCArIGldID0gKHZhbHVlID4+PiAobGl0dGxlRW5kaWFuID8gaSA6IDMgLSBpKSAqIDgpICYgMHhmZlxuICB9XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVVSW50MzJMRSA9IGZ1bmN0aW9uIHdyaXRlVUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHhmZmZmZmZmZiwgMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSA+Pj4gMjQpXG4gICAgdGhpc1tvZmZzZXQgKyAyXSA9ICh2YWx1ZSA+Pj4gMTYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZVVJbnQzMkJFID0gZnVuY3Rpb24gd3JpdGVVSW50MzJCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSBjaGVja0ludCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCA0LCAweGZmZmZmZmZmLCAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDI0KVxuICAgIHRoaXNbb2Zmc2V0ICsgMV0gPSAodmFsdWUgPj4+IDE2KVxuICAgIHRoaXNbb2Zmc2V0ICsgMl0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAzXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MzIodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDRcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludExFID0gZnVuY3Rpb24gd3JpdGVJbnRMRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGggLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICB2YXIgaSA9IDBcbiAgdmFyIG11bCA9IDFcbiAgdmFyIHN1YiA9IDBcbiAgdGhpc1tvZmZzZXRdID0gdmFsdWUgJiAweEZGXG4gIHdoaWxlICgrK2kgPCBieXRlTGVuZ3RoICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgaWYgKHZhbHVlIDwgMCAmJiBzdWIgPT09IDAgJiYgdGhpc1tvZmZzZXQgKyBpIC0gMV0gIT09IDApIHtcbiAgICAgIHN1YiA9IDFcbiAgICB9XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludEJFID0gZnVuY3Rpb24gd3JpdGVJbnRCRSAodmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbm9Bc3NlcnQpIHtcbiAgdmFsdWUgPSArdmFsdWVcbiAgb2Zmc2V0ID0gb2Zmc2V0IHwgMFxuICBpZiAoIW5vQXNzZXJ0KSB7XG4gICAgdmFyIGxpbWl0ID0gTWF0aC5wb3coMiwgOCAqIGJ5dGVMZW5ndGggLSAxKVxuXG4gICAgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgYnl0ZUxlbmd0aCwgbGltaXQgLSAxLCAtbGltaXQpXG4gIH1cblxuICB2YXIgaSA9IGJ5dGVMZW5ndGggLSAxXG4gIHZhciBtdWwgPSAxXG4gIHZhciBzdWIgPSAwXG4gIHRoaXNbb2Zmc2V0ICsgaV0gPSB2YWx1ZSAmIDB4RkZcbiAgd2hpbGUgKC0taSA+PSAwICYmIChtdWwgKj0gMHgxMDApKSB7XG4gICAgaWYgKHZhbHVlIDwgMCAmJiBzdWIgPT09IDAgJiYgdGhpc1tvZmZzZXQgKyBpICsgMV0gIT09IDApIHtcbiAgICAgIHN1YiA9IDFcbiAgICB9XG4gICAgdGhpc1tvZmZzZXQgKyBpXSA9ICgodmFsdWUgLyBtdWwpID4+IDApIC0gc3ViICYgMHhGRlxuICB9XG5cbiAgcmV0dXJuIG9mZnNldCArIGJ5dGVMZW5ndGhcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDggPSBmdW5jdGlvbiB3cml0ZUludDggKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMSwgMHg3ZiwgLTB4ODApXG4gIGlmICghQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHZhbHVlID0gTWF0aC5mbG9vcih2YWx1ZSlcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAweGZmICsgdmFsdWUgKyAxXG4gIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIHJldHVybiBvZmZzZXQgKyAxXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQxNkxFID0gZnVuY3Rpb24gd3JpdGVJbnQxNkxFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDIsIDB4N2ZmZiwgLTB4ODAwMClcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlICYgMHhmZilcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiA4KVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDE2KHRoaXMsIHZhbHVlLCBvZmZzZXQsIHRydWUpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDE2QkUgPSBmdW5jdGlvbiB3cml0ZUludDE2QkUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgMiwgMHg3ZmZmLCAtMHg4MDAwKVxuICBpZiAoQnVmZmVyLlRZUEVEX0FSUkFZX1NVUFBPUlQpIHtcbiAgICB0aGlzW29mZnNldF0gPSAodmFsdWUgPj4+IDgpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSAmIDB4ZmYpXG4gIH0gZWxzZSB7XG4gICAgb2JqZWN0V3JpdGVVSW50MTYodGhpcywgdmFsdWUsIG9mZnNldCwgZmFsc2UpXG4gIH1cbiAgcmV0dXJuIG9mZnNldCArIDJcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZUludDMyTEUgPSBmdW5jdGlvbiB3cml0ZUludDMyTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHZhbHVlID0gK3ZhbHVlXG4gIG9mZnNldCA9IG9mZnNldCB8IDBcbiAgaWYgKCFub0Fzc2VydCkgY2hlY2tJbnQodGhpcywgdmFsdWUsIG9mZnNldCwgNCwgMHg3ZmZmZmZmZiwgLTB4ODAwMDAwMDApXG4gIGlmIChCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIHRoaXNbb2Zmc2V0XSA9ICh2YWx1ZSAmIDB4ZmYpXG4gICAgdGhpc1tvZmZzZXQgKyAxXSA9ICh2YWx1ZSA+Pj4gOClcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDNdID0gKHZhbHVlID4+PiAyNClcbiAgfSBlbHNlIHtcbiAgICBvYmplY3RXcml0ZVVJbnQzMih0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVJbnQzMkJFID0gZnVuY3Rpb24gd3JpdGVJbnQzMkJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICB2YWx1ZSA9ICt2YWx1ZVxuICBvZmZzZXQgPSBvZmZzZXQgfCAwXG4gIGlmICghbm9Bc3NlcnQpIGNoZWNrSW50KHRoaXMsIHZhbHVlLCBvZmZzZXQsIDQsIDB4N2ZmZmZmZmYsIC0weDgwMDAwMDAwKVxuICBpZiAodmFsdWUgPCAwKSB2YWx1ZSA9IDB4ZmZmZmZmZmYgKyB2YWx1ZSArIDFcbiAgaWYgKEJ1ZmZlci5UWVBFRF9BUlJBWV9TVVBQT1JUKSB7XG4gICAgdGhpc1tvZmZzZXRdID0gKHZhbHVlID4+PiAyNClcbiAgICB0aGlzW29mZnNldCArIDFdID0gKHZhbHVlID4+PiAxNilcbiAgICB0aGlzW29mZnNldCArIDJdID0gKHZhbHVlID4+PiA4KVxuICAgIHRoaXNbb2Zmc2V0ICsgM10gPSAodmFsdWUgJiAweGZmKVxuICB9IGVsc2Uge1xuICAgIG9iamVjdFdyaXRlVUludDMyKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlKVxuICB9XG4gIHJldHVybiBvZmZzZXQgKyA0XG59XG5cbmZ1bmN0aW9uIGNoZWNrSUVFRTc1NCAoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBleHQsIG1heCwgbWluKSB7XG4gIGlmIChvZmZzZXQgKyBleHQgPiBidWYubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignSW5kZXggb3V0IG9mIHJhbmdlJylcbiAgaWYgKG9mZnNldCA8IDApIHRocm93IG5ldyBSYW5nZUVycm9yKCdJbmRleCBvdXQgb2YgcmFuZ2UnKVxufVxuXG5mdW5jdGlvbiB3cml0ZUZsb2F0IChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDQsIDMuNDAyODIzNDY2Mzg1Mjg4NmUrMzgsIC0zLjQwMjgyMzQ2NjM4NTI4ODZlKzM4KVxuICB9XG4gIGllZWU3NTQud3JpdGUoYnVmLCB2YWx1ZSwgb2Zmc2V0LCBsaXR0bGVFbmRpYW4sIDIzLCA0KVxuICByZXR1cm4gb2Zmc2V0ICsgNFxufVxuXG5CdWZmZXIucHJvdG90eXBlLndyaXRlRmxvYXRMRSA9IGZ1bmN0aW9uIHdyaXRlRmxvYXRMRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRmxvYXQodGhpcywgdmFsdWUsIG9mZnNldCwgdHJ1ZSwgbm9Bc3NlcnQpXG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVGbG9hdEJFID0gZnVuY3Rpb24gd3JpdGVGbG9hdEJFICh2YWx1ZSwgb2Zmc2V0LCBub0Fzc2VydCkge1xuICByZXR1cm4gd3JpdGVGbG9hdCh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCBmYWxzZSwgbm9Bc3NlcnQpXG59XG5cbmZ1bmN0aW9uIHdyaXRlRG91YmxlIChidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcbiAgaWYgKCFub0Fzc2VydCkge1xuICAgIGNoZWNrSUVFRTc1NChidWYsIHZhbHVlLCBvZmZzZXQsIDgsIDEuNzk3NjkzMTM0ODYyMzE1N0UrMzA4LCAtMS43OTc2OTMxMzQ4NjIzMTU3RSszMDgpXG4gIH1cbiAgaWVlZTc1NC53cml0ZShidWYsIHZhbHVlLCBvZmZzZXQsIGxpdHRsZUVuZGlhbiwgNTIsIDgpXG4gIHJldHVybiBvZmZzZXQgKyA4XG59XG5cbkJ1ZmZlci5wcm90b3R5cGUud3JpdGVEb3VibGVMRSA9IGZ1bmN0aW9uIHdyaXRlRG91YmxlTEUgKHZhbHVlLCBvZmZzZXQsIG5vQXNzZXJ0KSB7XG4gIHJldHVybiB3cml0ZURvdWJsZSh0aGlzLCB2YWx1ZSwgb2Zmc2V0LCB0cnVlLCBub0Fzc2VydClcbn1cblxuQnVmZmVyLnByb3RvdHlwZS53cml0ZURvdWJsZUJFID0gZnVuY3Rpb24gd3JpdGVEb3VibGVCRSAodmFsdWUsIG9mZnNldCwgbm9Bc3NlcnQpIHtcbiAgcmV0dXJuIHdyaXRlRG91YmxlKHRoaXMsIHZhbHVlLCBvZmZzZXQsIGZhbHNlLCBub0Fzc2VydClcbn1cblxuLy8gY29weSh0YXJnZXRCdWZmZXIsIHRhcmdldFN0YXJ0PTAsIHNvdXJjZVN0YXJ0PTAsIHNvdXJjZUVuZD1idWZmZXIubGVuZ3RoKVxuQnVmZmVyLnByb3RvdHlwZS5jb3B5ID0gZnVuY3Rpb24gY29weSAodGFyZ2V0LCB0YXJnZXRTdGFydCwgc3RhcnQsIGVuZCkge1xuICBpZiAoIXN0YXJ0KSBzdGFydCA9IDBcbiAgaWYgKCFlbmQgJiYgZW5kICE9PSAwKSBlbmQgPSB0aGlzLmxlbmd0aFxuICBpZiAodGFyZ2V0U3RhcnQgPj0gdGFyZ2V0Lmxlbmd0aCkgdGFyZ2V0U3RhcnQgPSB0YXJnZXQubGVuZ3RoXG4gIGlmICghdGFyZ2V0U3RhcnQpIHRhcmdldFN0YXJ0ID0gMFxuICBpZiAoZW5kID4gMCAmJiBlbmQgPCBzdGFydCkgZW5kID0gc3RhcnRcblxuICAvLyBDb3B5IDAgYnl0ZXM7IHdlJ3JlIGRvbmVcbiAgaWYgKGVuZCA9PT0gc3RhcnQpIHJldHVybiAwXG4gIGlmICh0YXJnZXQubGVuZ3RoID09PSAwIHx8IHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gMFxuXG4gIC8vIEZhdGFsIGVycm9yIGNvbmRpdGlvbnNcbiAgaWYgKHRhcmdldFN0YXJ0IDwgMCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCd0YXJnZXRTdGFydCBvdXQgb2YgYm91bmRzJylcbiAgfVxuICBpZiAoc3RhcnQgPCAwIHx8IHN0YXJ0ID49IHRoaXMubGVuZ3RoKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlU3RhcnQgb3V0IG9mIGJvdW5kcycpXG4gIGlmIChlbmQgPCAwKSB0aHJvdyBuZXcgUmFuZ2VFcnJvcignc291cmNlRW5kIG91dCBvZiBib3VuZHMnKVxuXG4gIC8vIEFyZSB3ZSBvb2I/XG4gIGlmIChlbmQgPiB0aGlzLmxlbmd0aCkgZW5kID0gdGhpcy5sZW5ndGhcbiAgaWYgKHRhcmdldC5sZW5ndGggLSB0YXJnZXRTdGFydCA8IGVuZCAtIHN0YXJ0KSB7XG4gICAgZW5kID0gdGFyZ2V0Lmxlbmd0aCAtIHRhcmdldFN0YXJ0ICsgc3RhcnRcbiAgfVxuXG4gIHZhciBsZW4gPSBlbmQgLSBzdGFydFxuICB2YXIgaVxuXG4gIGlmICh0aGlzID09PSB0YXJnZXQgJiYgc3RhcnQgPCB0YXJnZXRTdGFydCAmJiB0YXJnZXRTdGFydCA8IGVuZCkge1xuICAgIC8vIGRlc2NlbmRpbmcgY29weSBmcm9tIGVuZFxuICAgIGZvciAoaSA9IGxlbiAtIDE7IGkgPj0gMDsgLS1pKSB7XG4gICAgICB0YXJnZXRbaSArIHRhcmdldFN0YXJ0XSA9IHRoaXNbaSArIHN0YXJ0XVxuICAgIH1cbiAgfSBlbHNlIGlmIChsZW4gPCAxMDAwIHx8ICFCdWZmZXIuVFlQRURfQVJSQVlfU1VQUE9SVCkge1xuICAgIC8vIGFzY2VuZGluZyBjb3B5IGZyb20gc3RhcnRcbiAgICBmb3IgKGkgPSAwOyBpIDwgbGVuOyArK2kpIHtcbiAgICAgIHRhcmdldFtpICsgdGFyZ2V0U3RhcnRdID0gdGhpc1tpICsgc3RhcnRdXG4gICAgfVxuICB9IGVsc2Uge1xuICAgIFVpbnQ4QXJyYXkucHJvdG90eXBlLnNldC5jYWxsKFxuICAgICAgdGFyZ2V0LFxuICAgICAgdGhpcy5zdWJhcnJheShzdGFydCwgc3RhcnQgKyBsZW4pLFxuICAgICAgdGFyZ2V0U3RhcnRcbiAgICApXG4gIH1cblxuICByZXR1cm4gbGVuXG59XG5cbi8vIFVzYWdlOlxuLy8gICAgYnVmZmVyLmZpbGwobnVtYmVyWywgb2Zmc2V0WywgZW5kXV0pXG4vLyAgICBidWZmZXIuZmlsbChidWZmZXJbLCBvZmZzZXRbLCBlbmRdXSlcbi8vICAgIGJ1ZmZlci5maWxsKHN0cmluZ1ssIG9mZnNldFssIGVuZF1dWywgZW5jb2RpbmddKVxuQnVmZmVyLnByb3RvdHlwZS5maWxsID0gZnVuY3Rpb24gZmlsbCAodmFsLCBzdGFydCwgZW5kLCBlbmNvZGluZykge1xuICAvLyBIYW5kbGUgc3RyaW5nIGNhc2VzOlxuICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpIHtcbiAgICBpZiAodHlwZW9mIHN0YXJ0ID09PSAnc3RyaW5nJykge1xuICAgICAgZW5jb2RpbmcgPSBzdGFydFxuICAgICAgc3RhcnQgPSAwXG4gICAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICAgIH0gZWxzZSBpZiAodHlwZW9mIGVuZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGVuY29kaW5nID0gZW5kXG4gICAgICBlbmQgPSB0aGlzLmxlbmd0aFxuICAgIH1cbiAgICBpZiAodmFsLmxlbmd0aCA9PT0gMSkge1xuICAgICAgdmFyIGNvZGUgPSB2YWwuY2hhckNvZGVBdCgwKVxuICAgICAgaWYgKGNvZGUgPCAyNTYpIHtcbiAgICAgICAgdmFsID0gY29kZVxuICAgICAgfVxuICAgIH1cbiAgICBpZiAoZW5jb2RpbmcgIT09IHVuZGVmaW5lZCAmJiB0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdlbmNvZGluZyBtdXN0IGJlIGEgc3RyaW5nJylcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBlbmNvZGluZyA9PT0gJ3N0cmluZycgJiYgIUJ1ZmZlci5pc0VuY29kaW5nKGVuY29kaW5nKSkge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKVxuICAgIH1cbiAgfSBlbHNlIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgIHZhbCA9IHZhbCAmIDI1NVxuICB9XG5cbiAgLy8gSW52YWxpZCByYW5nZXMgYXJlIG5vdCBzZXQgdG8gYSBkZWZhdWx0LCBzbyBjYW4gcmFuZ2UgY2hlY2sgZWFybHkuXG4gIGlmIChzdGFydCA8IDAgfHwgdGhpcy5sZW5ndGggPCBzdGFydCB8fCB0aGlzLmxlbmd0aCA8IGVuZCkge1xuICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdPdXQgb2YgcmFuZ2UgaW5kZXgnKVxuICB9XG5cbiAgaWYgKGVuZCA8PSBzdGFydCkge1xuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBzdGFydCA9IHN0YXJ0ID4+PiAwXG4gIGVuZCA9IGVuZCA9PT0gdW5kZWZpbmVkID8gdGhpcy5sZW5ndGggOiBlbmQgPj4+IDBcblxuICBpZiAoIXZhbCkgdmFsID0gMFxuXG4gIHZhciBpXG4gIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJykge1xuICAgIGZvciAoaSA9IHN0YXJ0OyBpIDwgZW5kOyArK2kpIHtcbiAgICAgIHRoaXNbaV0gPSB2YWxcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgdmFyIGJ5dGVzID0gQnVmZmVyLmlzQnVmZmVyKHZhbClcbiAgICAgID8gdmFsXG4gICAgICA6IHV0ZjhUb0J5dGVzKG5ldyBCdWZmZXIodmFsLCBlbmNvZGluZykudG9TdHJpbmcoKSlcbiAgICB2YXIgbGVuID0gYnl0ZXMubGVuZ3RoXG4gICAgZm9yIChpID0gMDsgaSA8IGVuZCAtIHN0YXJ0OyArK2kpIHtcbiAgICAgIHRoaXNbaSArIHN0YXJ0XSA9IGJ5dGVzW2kgJSBsZW5dXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRoaXNcbn1cblxuLy8gSEVMUEVSIEZVTkNUSU9OU1xuLy8gPT09PT09PT09PT09PT09PVxuXG52YXIgSU5WQUxJRF9CQVNFNjRfUkUgPSAvW14rXFwvMC05QS1aYS16LV9dL2dcblxuZnVuY3Rpb24gYmFzZTY0Y2xlYW4gKHN0cikge1xuICAvLyBOb2RlIHN0cmlwcyBvdXQgaW52YWxpZCBjaGFyYWN0ZXJzIGxpa2UgXFxuIGFuZCBcXHQgZnJvbSB0aGUgc3RyaW5nLCBiYXNlNjQtanMgZG9lcyBub3RcbiAgc3RyID0gc3RyaW5ndHJpbShzdHIpLnJlcGxhY2UoSU5WQUxJRF9CQVNFNjRfUkUsICcnKVxuICAvLyBOb2RlIGNvbnZlcnRzIHN0cmluZ3Mgd2l0aCBsZW5ndGggPCAyIHRvICcnXG4gIGlmIChzdHIubGVuZ3RoIDwgMikgcmV0dXJuICcnXG4gIC8vIE5vZGUgYWxsb3dzIGZvciBub24tcGFkZGVkIGJhc2U2NCBzdHJpbmdzIChtaXNzaW5nIHRyYWlsaW5nID09PSksIGJhc2U2NC1qcyBkb2VzIG5vdFxuICB3aGlsZSAoc3RyLmxlbmd0aCAlIDQgIT09IDApIHtcbiAgICBzdHIgPSBzdHIgKyAnPSdcbiAgfVxuICByZXR1cm4gc3RyXG59XG5cbmZ1bmN0aW9uIHN0cmluZ3RyaW0gKHN0cikge1xuICBpZiAoc3RyLnRyaW0pIHJldHVybiBzdHIudHJpbSgpXG4gIHJldHVybiBzdHIucmVwbGFjZSgvXlxccyt8XFxzKyQvZywgJycpXG59XG5cbmZ1bmN0aW9uIHRvSGV4IChuKSB7XG4gIGlmIChuIDwgMTYpIHJldHVybiAnMCcgKyBuLnRvU3RyaW5nKDE2KVxuICByZXR1cm4gbi50b1N0cmluZygxNilcbn1cblxuZnVuY3Rpb24gdXRmOFRvQnl0ZXMgKHN0cmluZywgdW5pdHMpIHtcbiAgdW5pdHMgPSB1bml0cyB8fCBJbmZpbml0eVxuICB2YXIgY29kZVBvaW50XG4gIHZhciBsZW5ndGggPSBzdHJpbmcubGVuZ3RoXG4gIHZhciBsZWFkU3Vycm9nYXRlID0gbnVsbFxuICB2YXIgYnl0ZXMgPSBbXVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBjb2RlUG9pbnQgPSBzdHJpbmcuY2hhckNvZGVBdChpKVxuXG4gICAgLy8gaXMgc3Vycm9nYXRlIGNvbXBvbmVudFxuICAgIGlmIChjb2RlUG9pbnQgPiAweEQ3RkYgJiYgY29kZVBvaW50IDwgMHhFMDAwKSB7XG4gICAgICAvLyBsYXN0IGNoYXIgd2FzIGEgbGVhZFxuICAgICAgaWYgKCFsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAgIC8vIG5vIGxlYWQgeWV0XG4gICAgICAgIGlmIChjb2RlUG9pbnQgPiAweERCRkYpIHtcbiAgICAgICAgICAvLyB1bmV4cGVjdGVkIHRyYWlsXG4gICAgICAgICAgaWYgKCh1bml0cyAtPSAzKSA+IC0xKSBieXRlcy5wdXNoKDB4RUYsIDB4QkYsIDB4QkQpXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfSBlbHNlIGlmIChpICsgMSA9PT0gbGVuZ3RoKSB7XG4gICAgICAgICAgLy8gdW5wYWlyZWQgbGVhZFxuICAgICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICAvLyB2YWxpZCBsZWFkXG4gICAgICAgIGxlYWRTdXJyb2dhdGUgPSBjb2RlUG9pbnRcblxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICAvLyAyIGxlYWRzIGluIGEgcm93XG4gICAgICBpZiAoY29kZVBvaW50IDwgMHhEQzAwKSB7XG4gICAgICAgIGlmICgodW5pdHMgLT0gMykgPiAtMSkgYnl0ZXMucHVzaCgweEVGLCAweEJGLCAweEJEKVxuICAgICAgICBsZWFkU3Vycm9nYXRlID0gY29kZVBvaW50XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIC8vIHZhbGlkIHN1cnJvZ2F0ZSBwYWlyXG4gICAgICBjb2RlUG9pbnQgPSAobGVhZFN1cnJvZ2F0ZSAtIDB4RDgwMCA8PCAxMCB8IGNvZGVQb2ludCAtIDB4REMwMCkgKyAweDEwMDAwXG4gICAgfSBlbHNlIGlmIChsZWFkU3Vycm9nYXRlKSB7XG4gICAgICAvLyB2YWxpZCBibXAgY2hhciwgYnV0IGxhc3QgY2hhciB3YXMgYSBsZWFkXG4gICAgICBpZiAoKHVuaXRzIC09IDMpID4gLTEpIGJ5dGVzLnB1c2goMHhFRiwgMHhCRiwgMHhCRClcbiAgICB9XG5cbiAgICBsZWFkU3Vycm9nYXRlID0gbnVsbFxuXG4gICAgLy8gZW5jb2RlIHV0ZjhcbiAgICBpZiAoY29kZVBvaW50IDwgMHg4MCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAxKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKGNvZGVQb2ludClcbiAgICB9IGVsc2UgaWYgKGNvZGVQb2ludCA8IDB4ODAwKSB7XG4gICAgICBpZiAoKHVuaXRzIC09IDIpIDwgMCkgYnJlYWtcbiAgICAgIGJ5dGVzLnB1c2goXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgfCAweEMwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMDAwMCkge1xuICAgICAgaWYgKCh1bml0cyAtPSAzKSA8IDApIGJyZWFrXG4gICAgICBieXRlcy5wdXNoKFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDIHwgMHhFMCxcbiAgICAgICAgY29kZVBvaW50ID4+IDB4NiAmIDB4M0YgfCAweDgwLFxuICAgICAgICBjb2RlUG9pbnQgJiAweDNGIHwgMHg4MFxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoY29kZVBvaW50IDwgMHgxMTAwMDApIHtcbiAgICAgIGlmICgodW5pdHMgLT0gNCkgPCAwKSBicmVha1xuICAgICAgYnl0ZXMucHVzaChcbiAgICAgICAgY29kZVBvaW50ID4+IDB4MTIgfCAweEYwLFxuICAgICAgICBjb2RlUG9pbnQgPj4gMHhDICYgMHgzRiB8IDB4ODAsXG4gICAgICAgIGNvZGVQb2ludCA+PiAweDYgJiAweDNGIHwgMHg4MCxcbiAgICAgICAgY29kZVBvaW50ICYgMHgzRiB8IDB4ODBcbiAgICAgIClcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIGNvZGUgcG9pbnQnKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBieXRlc1xufVxuXG5mdW5jdGlvbiBhc2NpaVRvQnl0ZXMgKHN0cikge1xuICB2YXIgYnl0ZUFycmF5ID0gW11cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCBzdHIubGVuZ3RoOyArK2kpIHtcbiAgICAvLyBOb2RlJ3MgY29kZSBzZWVtcyB0byBiZSBkb2luZyB0aGlzIGFuZCBub3QgJiAweDdGLi5cbiAgICBieXRlQXJyYXkucHVzaChzdHIuY2hhckNvZGVBdChpKSAmIDB4RkYpXG4gIH1cbiAgcmV0dXJuIGJ5dGVBcnJheVxufVxuXG5mdW5jdGlvbiB1dGYxNmxlVG9CeXRlcyAoc3RyLCB1bml0cykge1xuICB2YXIgYywgaGksIGxvXG4gIHZhciBieXRlQXJyYXkgPSBbXVxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7ICsraSkge1xuICAgIGlmICgodW5pdHMgLT0gMikgPCAwKSBicmVha1xuXG4gICAgYyA9IHN0ci5jaGFyQ29kZUF0KGkpXG4gICAgaGkgPSBjID4+IDhcbiAgICBsbyA9IGMgJSAyNTZcbiAgICBieXRlQXJyYXkucHVzaChsbylcbiAgICBieXRlQXJyYXkucHVzaChoaSlcbiAgfVxuXG4gIHJldHVybiBieXRlQXJyYXlcbn1cblxuZnVuY3Rpb24gYmFzZTY0VG9CeXRlcyAoc3RyKSB7XG4gIHJldHVybiBiYXNlNjQudG9CeXRlQXJyYXkoYmFzZTY0Y2xlYW4oc3RyKSlcbn1cblxuZnVuY3Rpb24gYmxpdEJ1ZmZlciAoc3JjLCBkc3QsIG9mZnNldCwgbGVuZ3RoKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcbiAgICBpZiAoKGkgKyBvZmZzZXQgPj0gZHN0Lmxlbmd0aCkgfHwgKGkgPj0gc3JjLmxlbmd0aCkpIGJyZWFrXG4gICAgZHN0W2kgKyBvZmZzZXRdID0gc3JjW2ldXG4gIH1cbiAgcmV0dXJuIGlcbn1cblxuZnVuY3Rpb24gaXNuYW4gKHZhbCkge1xuICByZXR1cm4gdmFsICE9PSB2YWwgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1zZWxmLWNvbXBhcmVcbn1cbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnYnVmZmVyJykuQnVmZmVyO1xuXG52YXIgaXNCdWZmZXJFbmNvZGluZyA9IEJ1ZmZlci5pc0VuY29kaW5nXG4gIHx8IGZ1bmN0aW9uKGVuY29kaW5nKSB7XG4gICAgICAgc3dpdGNoIChlbmNvZGluZyAmJiBlbmNvZGluZy50b0xvd2VyQ2FzZSgpKSB7XG4gICAgICAgICBjYXNlICdoZXgnOiBjYXNlICd1dGY4JzogY2FzZSAndXRmLTgnOiBjYXNlICdhc2NpaSc6IGNhc2UgJ2JpbmFyeSc6IGNhc2UgJ2Jhc2U2NCc6IGNhc2UgJ3VjczInOiBjYXNlICd1Y3MtMic6IGNhc2UgJ3V0ZjE2bGUnOiBjYXNlICd1dGYtMTZsZSc6IGNhc2UgJ3Jhdyc6IHJldHVybiB0cnVlO1xuICAgICAgICAgZGVmYXVsdDogcmV0dXJuIGZhbHNlO1xuICAgICAgIH1cbiAgICAgfVxuXG5cbmZ1bmN0aW9uIGFzc2VydEVuY29kaW5nKGVuY29kaW5nKSB7XG4gIGlmIChlbmNvZGluZyAmJiAhaXNCdWZmZXJFbmNvZGluZyhlbmNvZGluZykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ1Vua25vd24gZW5jb2Rpbmc6ICcgKyBlbmNvZGluZyk7XG4gIH1cbn1cblxuLy8gU3RyaW5nRGVjb2RlciBwcm92aWRlcyBhbiBpbnRlcmZhY2UgZm9yIGVmZmljaWVudGx5IHNwbGl0dGluZyBhIHNlcmllcyBvZlxuLy8gYnVmZmVycyBpbnRvIGEgc2VyaWVzIG9mIEpTIHN0cmluZ3Mgd2l0aG91dCBicmVha2luZyBhcGFydCBtdWx0aS1ieXRlXG4vLyBjaGFyYWN0ZXJzLiBDRVNVLTggaXMgaGFuZGxlZCBhcyBwYXJ0IG9mIHRoZSBVVEYtOCBlbmNvZGluZy5cbi8vXG4vLyBAVE9ETyBIYW5kbGluZyBhbGwgZW5jb2RpbmdzIGluc2lkZSBhIHNpbmdsZSBvYmplY3QgbWFrZXMgaXQgdmVyeSBkaWZmaWN1bHRcbi8vIHRvIHJlYXNvbiBhYm91dCB0aGlzIGNvZGUsIHNvIGl0IHNob3VsZCBiZSBzcGxpdCB1cCBpbiB0aGUgZnV0dXJlLlxuLy8gQFRPRE8gVGhlcmUgc2hvdWxkIGJlIGEgdXRmOC1zdHJpY3QgZW5jb2RpbmcgdGhhdCByZWplY3RzIGludmFsaWQgVVRGLTggY29kZVxuLy8gcG9pbnRzIGFzIHVzZWQgYnkgQ0VTVS04LlxudmFyIFN0cmluZ0RlY29kZXIgPSBleHBvcnRzLlN0cmluZ0RlY29kZXIgPSBmdW5jdGlvbihlbmNvZGluZykge1xuICB0aGlzLmVuY29kaW5nID0gKGVuY29kaW5nIHx8ICd1dGY4JykudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9bLV9dLywgJycpO1xuICBhc3NlcnRFbmNvZGluZyhlbmNvZGluZyk7XG4gIHN3aXRjaCAodGhpcy5lbmNvZGluZykge1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgLy8gQ0VTVS04IHJlcHJlc2VudHMgZWFjaCBvZiBTdXJyb2dhdGUgUGFpciBieSAzLWJ5dGVzXG4gICAgICB0aGlzLnN1cnJvZ2F0ZVNpemUgPSAzO1xuICAgICAgYnJlYWs7XG4gICAgY2FzZSAndWNzMic6XG4gICAgY2FzZSAndXRmMTZsZSc6XG4gICAgICAvLyBVVEYtMTYgcmVwcmVzZW50cyBlYWNoIG9mIFN1cnJvZ2F0ZSBQYWlyIGJ5IDItYnl0ZXNcbiAgICAgIHRoaXMuc3Vycm9nYXRlU2l6ZSA9IDI7XG4gICAgICB0aGlzLmRldGVjdEluY29tcGxldGVDaGFyID0gdXRmMTZEZXRlY3RJbmNvbXBsZXRlQ2hhcjtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICAvLyBCYXNlLTY0IHN0b3JlcyAzIGJ5dGVzIGluIDQgY2hhcnMsIGFuZCBwYWRzIHRoZSByZW1haW5kZXIuXG4gICAgICB0aGlzLnN1cnJvZ2F0ZVNpemUgPSAzO1xuICAgICAgdGhpcy5kZXRlY3RJbmNvbXBsZXRlQ2hhciA9IGJhc2U2NERldGVjdEluY29tcGxldGVDaGFyO1xuICAgICAgYnJlYWs7XG4gICAgZGVmYXVsdDpcbiAgICAgIHRoaXMud3JpdGUgPSBwYXNzVGhyb3VnaFdyaXRlO1xuICAgICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gRW5vdWdoIHNwYWNlIHRvIHN0b3JlIGFsbCBieXRlcyBvZiBhIHNpbmdsZSBjaGFyYWN0ZXIuIFVURi04IG5lZWRzIDRcbiAgLy8gYnl0ZXMsIGJ1dCBDRVNVLTggbWF5IHJlcXVpcmUgdXAgdG8gNiAoMyBieXRlcyBwZXIgc3Vycm9nYXRlKS5cbiAgdGhpcy5jaGFyQnVmZmVyID0gbmV3IEJ1ZmZlcig2KTtcbiAgLy8gTnVtYmVyIG9mIGJ5dGVzIHJlY2VpdmVkIGZvciB0aGUgY3VycmVudCBpbmNvbXBsZXRlIG11bHRpLWJ5dGUgY2hhcmFjdGVyLlxuICB0aGlzLmNoYXJSZWNlaXZlZCA9IDA7XG4gIC8vIE51bWJlciBvZiBieXRlcyBleHBlY3RlZCBmb3IgdGhlIGN1cnJlbnQgaW5jb21wbGV0ZSBtdWx0aS1ieXRlIGNoYXJhY3Rlci5cbiAgdGhpcy5jaGFyTGVuZ3RoID0gMDtcbn07XG5cblxuLy8gd3JpdGUgZGVjb2RlcyB0aGUgZ2l2ZW4gYnVmZmVyIGFuZCByZXR1cm5zIGl0IGFzIEpTIHN0cmluZyB0aGF0IGlzXG4vLyBndWFyYW50ZWVkIHRvIG5vdCBjb250YWluIGFueSBwYXJ0aWFsIG11bHRpLWJ5dGUgY2hhcmFjdGVycy4gQW55IHBhcnRpYWxcbi8vIGNoYXJhY3RlciBmb3VuZCBhdCB0aGUgZW5kIG9mIHRoZSBidWZmZXIgaXMgYnVmZmVyZWQgdXAsIGFuZCB3aWxsIGJlXG4vLyByZXR1cm5lZCB3aGVuIGNhbGxpbmcgd3JpdGUgYWdhaW4gd2l0aCB0aGUgcmVtYWluaW5nIGJ5dGVzLlxuLy9cbi8vIE5vdGU6IENvbnZlcnRpbmcgYSBCdWZmZXIgY29udGFpbmluZyBhbiBvcnBoYW4gc3Vycm9nYXRlIHRvIGEgU3RyaW5nXG4vLyBjdXJyZW50bHkgd29ya3MsIGJ1dCBjb252ZXJ0aW5nIGEgU3RyaW5nIHRvIGEgQnVmZmVyICh2aWEgYG5ldyBCdWZmZXJgLCBvclxuLy8gQnVmZmVyI3dyaXRlKSB3aWxsIHJlcGxhY2UgaW5jb21wbGV0ZSBzdXJyb2dhdGVzIHdpdGggdGhlIHVuaWNvZGVcbi8vIHJlcGxhY2VtZW50IGNoYXJhY3Rlci4gU2VlIGh0dHBzOi8vY29kZXJldmlldy5jaHJvbWl1bS5vcmcvMTIxMTczMDA5LyAuXG5TdHJpbmdEZWNvZGVyLnByb3RvdHlwZS53cml0ZSA9IGZ1bmN0aW9uKGJ1ZmZlcikge1xuICB2YXIgY2hhclN0ciA9ICcnO1xuICAvLyBpZiBvdXIgbGFzdCB3cml0ZSBlbmRlZCB3aXRoIGFuIGluY29tcGxldGUgbXVsdGlieXRlIGNoYXJhY3RlclxuICB3aGlsZSAodGhpcy5jaGFyTGVuZ3RoKSB7XG4gICAgLy8gZGV0ZXJtaW5lIGhvdyBtYW55IHJlbWFpbmluZyBieXRlcyB0aGlzIGJ1ZmZlciBoYXMgdG8gb2ZmZXIgZm9yIHRoaXMgY2hhclxuICAgIHZhciBhdmFpbGFibGUgPSAoYnVmZmVyLmxlbmd0aCA+PSB0aGlzLmNoYXJMZW5ndGggLSB0aGlzLmNoYXJSZWNlaXZlZCkgP1xuICAgICAgICB0aGlzLmNoYXJMZW5ndGggLSB0aGlzLmNoYXJSZWNlaXZlZCA6XG4gICAgICAgIGJ1ZmZlci5sZW5ndGg7XG5cbiAgICAvLyBhZGQgdGhlIG5ldyBieXRlcyB0byB0aGUgY2hhciBidWZmZXJcbiAgICBidWZmZXIuY29weSh0aGlzLmNoYXJCdWZmZXIsIHRoaXMuY2hhclJlY2VpdmVkLCAwLCBhdmFpbGFibGUpO1xuICAgIHRoaXMuY2hhclJlY2VpdmVkICs9IGF2YWlsYWJsZTtcblxuICAgIGlmICh0aGlzLmNoYXJSZWNlaXZlZCA8IHRoaXMuY2hhckxlbmd0aCkge1xuICAgICAgLy8gc3RpbGwgbm90IGVub3VnaCBjaGFycyBpbiB0aGlzIGJ1ZmZlcj8gd2FpdCBmb3IgbW9yZSAuLi5cbiAgICAgIHJldHVybiAnJztcbiAgICB9XG5cbiAgICAvLyByZW1vdmUgYnl0ZXMgYmVsb25naW5nIHRvIHRoZSBjdXJyZW50IGNoYXJhY3RlciBmcm9tIHRoZSBidWZmZXJcbiAgICBidWZmZXIgPSBidWZmZXIuc2xpY2UoYXZhaWxhYmxlLCBidWZmZXIubGVuZ3RoKTtcblxuICAgIC8vIGdldCB0aGUgY2hhcmFjdGVyIHRoYXQgd2FzIHNwbGl0XG4gICAgY2hhclN0ciA9IHRoaXMuY2hhckJ1ZmZlci5zbGljZSgwLCB0aGlzLmNoYXJMZW5ndGgpLnRvU3RyaW5nKHRoaXMuZW5jb2RpbmcpO1xuXG4gICAgLy8gQ0VTVS04OiBsZWFkIHN1cnJvZ2F0ZSAoRDgwMC1EQkZGKSBpcyBhbHNvIHRoZSBpbmNvbXBsZXRlIGNoYXJhY3RlclxuICAgIHZhciBjaGFyQ29kZSA9IGNoYXJTdHIuY2hhckNvZGVBdChjaGFyU3RyLmxlbmd0aCAtIDEpO1xuICAgIGlmIChjaGFyQ29kZSA+PSAweEQ4MDAgJiYgY2hhckNvZGUgPD0gMHhEQkZGKSB7XG4gICAgICB0aGlzLmNoYXJMZW5ndGggKz0gdGhpcy5zdXJyb2dhdGVTaXplO1xuICAgICAgY2hhclN0ciA9ICcnO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIHRoaXMuY2hhclJlY2VpdmVkID0gdGhpcy5jaGFyTGVuZ3RoID0gMDtcblxuICAgIC8vIGlmIHRoZXJlIGFyZSBubyBtb3JlIGJ5dGVzIGluIHRoaXMgYnVmZmVyLCBqdXN0IGVtaXQgb3VyIGNoYXJcbiAgICBpZiAoYnVmZmVyLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIGNoYXJTdHI7XG4gICAgfVxuICAgIGJyZWFrO1xuICB9XG5cbiAgLy8gZGV0ZXJtaW5lIGFuZCBzZXQgY2hhckxlbmd0aCAvIGNoYXJSZWNlaXZlZFxuICB0aGlzLmRldGVjdEluY29tcGxldGVDaGFyKGJ1ZmZlcik7XG5cbiAgdmFyIGVuZCA9IGJ1ZmZlci5sZW5ndGg7XG4gIGlmICh0aGlzLmNoYXJMZW5ndGgpIHtcbiAgICAvLyBidWZmZXIgdGhlIGluY29tcGxldGUgY2hhcmFjdGVyIGJ5dGVzIHdlIGdvdFxuICAgIGJ1ZmZlci5jb3B5KHRoaXMuY2hhckJ1ZmZlciwgMCwgYnVmZmVyLmxlbmd0aCAtIHRoaXMuY2hhclJlY2VpdmVkLCBlbmQpO1xuICAgIGVuZCAtPSB0aGlzLmNoYXJSZWNlaXZlZDtcbiAgfVxuXG4gIGNoYXJTdHIgKz0gYnVmZmVyLnRvU3RyaW5nKHRoaXMuZW5jb2RpbmcsIDAsIGVuZCk7XG5cbiAgdmFyIGVuZCA9IGNoYXJTdHIubGVuZ3RoIC0gMTtcbiAgdmFyIGNoYXJDb2RlID0gY2hhclN0ci5jaGFyQ29kZUF0KGVuZCk7XG4gIC8vIENFU1UtODogbGVhZCBzdXJyb2dhdGUgKEQ4MDAtREJGRikgaXMgYWxzbyB0aGUgaW5jb21wbGV0ZSBjaGFyYWN0ZXJcbiAgaWYgKGNoYXJDb2RlID49IDB4RDgwMCAmJiBjaGFyQ29kZSA8PSAweERCRkYpIHtcbiAgICB2YXIgc2l6ZSA9IHRoaXMuc3Vycm9nYXRlU2l6ZTtcbiAgICB0aGlzLmNoYXJMZW5ndGggKz0gc2l6ZTtcbiAgICB0aGlzLmNoYXJSZWNlaXZlZCArPSBzaXplO1xuICAgIHRoaXMuY2hhckJ1ZmZlci5jb3B5KHRoaXMuY2hhckJ1ZmZlciwgc2l6ZSwgMCwgc2l6ZSk7XG4gICAgYnVmZmVyLmNvcHkodGhpcy5jaGFyQnVmZmVyLCAwLCAwLCBzaXplKTtcbiAgICByZXR1cm4gY2hhclN0ci5zdWJzdHJpbmcoMCwgZW5kKTtcbiAgfVxuXG4gIC8vIG9yIGp1c3QgZW1pdCB0aGUgY2hhclN0clxuICByZXR1cm4gY2hhclN0cjtcbn07XG5cbi8vIGRldGVjdEluY29tcGxldGVDaGFyIGRldGVybWluZXMgaWYgdGhlcmUgaXMgYW4gaW5jb21wbGV0ZSBVVEYtOCBjaGFyYWN0ZXIgYXRcbi8vIHRoZSBlbmQgb2YgdGhlIGdpdmVuIGJ1ZmZlci4gSWYgc28sIGl0IHNldHMgdGhpcy5jaGFyTGVuZ3RoIHRvIHRoZSBieXRlXG4vLyBsZW5ndGggdGhhdCBjaGFyYWN0ZXIsIGFuZCBzZXRzIHRoaXMuY2hhclJlY2VpdmVkIHRvIHRoZSBudW1iZXIgb2YgYnl0ZXNcbi8vIHRoYXQgYXJlIGF2YWlsYWJsZSBmb3IgdGhpcyBjaGFyYWN0ZXIuXG5TdHJpbmdEZWNvZGVyLnByb3RvdHlwZS5kZXRlY3RJbmNvbXBsZXRlQ2hhciA9IGZ1bmN0aW9uKGJ1ZmZlcikge1xuICAvLyBkZXRlcm1pbmUgaG93IG1hbnkgYnl0ZXMgd2UgaGF2ZSB0byBjaGVjayBhdCB0aGUgZW5kIG9mIHRoaXMgYnVmZmVyXG4gIHZhciBpID0gKGJ1ZmZlci5sZW5ndGggPj0gMykgPyAzIDogYnVmZmVyLmxlbmd0aDtcblxuICAvLyBGaWd1cmUgb3V0IGlmIG9uZSBvZiB0aGUgbGFzdCBpIGJ5dGVzIG9mIG91ciBidWZmZXIgYW5ub3VuY2VzIGFuXG4gIC8vIGluY29tcGxldGUgY2hhci5cbiAgZm9yICg7IGkgPiAwOyBpLS0pIHtcbiAgICB2YXIgYyA9IGJ1ZmZlcltidWZmZXIubGVuZ3RoIC0gaV07XG5cbiAgICAvLyBTZWUgaHR0cDovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9VVEYtOCNEZXNjcmlwdGlvblxuXG4gICAgLy8gMTEwWFhYWFhcbiAgICBpZiAoaSA9PSAxICYmIGMgPj4gNSA9PSAweDA2KSB7XG4gICAgICB0aGlzLmNoYXJMZW5ndGggPSAyO1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgLy8gMTExMFhYWFhcbiAgICBpZiAoaSA8PSAyICYmIGMgPj4gNCA9PSAweDBFKSB7XG4gICAgICB0aGlzLmNoYXJMZW5ndGggPSAzO1xuICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgLy8gMTExMTBYWFhcbiAgICBpZiAoaSA8PSAzICYmIGMgPj4gMyA9PSAweDFFKSB7XG4gICAgICB0aGlzLmNoYXJMZW5ndGggPSA0O1xuICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG4gIHRoaXMuY2hhclJlY2VpdmVkID0gaTtcbn07XG5cblN0cmluZ0RlY29kZXIucHJvdG90eXBlLmVuZCA9IGZ1bmN0aW9uKGJ1ZmZlcikge1xuICB2YXIgcmVzID0gJyc7XG4gIGlmIChidWZmZXIgJiYgYnVmZmVyLmxlbmd0aClcbiAgICByZXMgPSB0aGlzLndyaXRlKGJ1ZmZlcik7XG5cbiAgaWYgKHRoaXMuY2hhclJlY2VpdmVkKSB7XG4gICAgdmFyIGNyID0gdGhpcy5jaGFyUmVjZWl2ZWQ7XG4gICAgdmFyIGJ1ZiA9IHRoaXMuY2hhckJ1ZmZlcjtcbiAgICB2YXIgZW5jID0gdGhpcy5lbmNvZGluZztcbiAgICByZXMgKz0gYnVmLnNsaWNlKDAsIGNyKS50b1N0cmluZyhlbmMpO1xuICB9XG5cbiAgcmV0dXJuIHJlcztcbn07XG5cbmZ1bmN0aW9uIHBhc3NUaHJvdWdoV3JpdGUoYnVmZmVyKSB7XG4gIHJldHVybiBidWZmZXIudG9TdHJpbmcodGhpcy5lbmNvZGluZyk7XG59XG5cbmZ1bmN0aW9uIHV0ZjE2RGV0ZWN0SW5jb21wbGV0ZUNoYXIoYnVmZmVyKSB7XG4gIHRoaXMuY2hhclJlY2VpdmVkID0gYnVmZmVyLmxlbmd0aCAlIDI7XG4gIHRoaXMuY2hhckxlbmd0aCA9IHRoaXMuY2hhclJlY2VpdmVkID8gMiA6IDA7XG59XG5cbmZ1bmN0aW9uIGJhc2U2NERldGVjdEluY29tcGxldGVDaGFyKGJ1ZmZlcikge1xuICB0aGlzLmNoYXJSZWNlaXZlZCA9IGJ1ZmZlci5sZW5ndGggJSAzO1xuICB0aGlzLmNoYXJMZW5ndGggPSB0aGlzLmNoYXJSZWNlaXZlZCA/IDMgOiAwO1xufVxuIiwidmFyIGJhc2V4ID0gcmVxdWlyZSgnYmFzZS14JylcbnZhciBBTFBIQUJFVCA9ICcxMjM0NTY3ODlBQkNERUZHSEpLTE1OUFFSU1RVVldYWVphYmNkZWZnaGlqa21ub3BxcnN0dXZ3eHl6J1xuXG5tb2R1bGUuZXhwb3J0cyA9IGJhc2V4KEFMUEhBQkVUKVxuIiwiLypcclxuIENvcHlyaWdodCAyMDEzLTIwMTQgRGFuaWVsIFdpcnR6IDxkY29kZUBkY29kZS5pbz5cclxuXHJcbiBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgXCJMaWNlbnNlXCIpO1xyXG4geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxyXG4gWW91IG1heSBvYnRhaW4gYSBjb3B5IG9mIHRoZSBMaWNlbnNlIGF0XHJcblxyXG4gaHR0cDovL3d3dy5hcGFjaGUub3JnL2xpY2Vuc2VzL0xJQ0VOU0UtMi4wXHJcblxyXG4gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxyXG4gZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIEJBU0lTLFxyXG4gV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXHJcbiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXHJcbiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cclxuICovXHJcblxyXG4vKipcclxuICogQGxpY2Vuc2UgYnl0ZWJ1ZmZlci5qcyAoYykgMjAxNSBEYW5pZWwgV2lydHogPGRjb2RlQGRjb2RlLmlvPlxyXG4gKiBCYWNraW5nIGJ1ZmZlcjogQXJyYXlCdWZmZXIsIEFjY2Vzc29yOiBVaW50OEFycmF5XHJcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjBcclxuICogc2VlOiBodHRwczovL2dpdGh1Yi5jb20vZGNvZGVJTy9ieXRlYnVmZmVyLmpzIGZvciBkZXRhaWxzXHJcbiAqL1xyXG4oZnVuY3Rpb24oZ2xvYmFsLCBmYWN0b3J5KSB7XHJcblxyXG4gICAgLyogQU1EICovIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZVtcImFtZFwiXSlcclxuICAgICAgICBkZWZpbmUoW1wibG9uZ1wiXSwgZmFjdG9yeSk7XHJcbiAgICAvKiBDb21tb25KUyAqLyBlbHNlIGlmICh0eXBlb2YgcmVxdWlyZSA9PT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgbW9kdWxlID09PSBcIm9iamVjdFwiICYmIG1vZHVsZSAmJiBtb2R1bGVbXCJleHBvcnRzXCJdKVxyXG4gICAgICAgIG1vZHVsZVsnZXhwb3J0cyddID0gKGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICB2YXIgTG9uZzsgdHJ5IHsgTG9uZyA9IHJlcXVpcmUoXCJsb25nXCIpOyB9IGNhdGNoIChlKSB7fVxyXG4gICAgICAgICAgICByZXR1cm4gZmFjdG9yeShMb25nKTtcclxuICAgICAgICB9KSgpO1xyXG4gICAgLyogR2xvYmFsICovIGVsc2VcclxuICAgICAgICAoZ2xvYmFsW1wiZGNvZGVJT1wiXSA9IGdsb2JhbFtcImRjb2RlSU9cIl0gfHwge30pW1wiQnl0ZUJ1ZmZlclwiXSA9IGZhY3RvcnkoZ2xvYmFsW1wiZGNvZGVJT1wiXVtcIkxvbmdcIl0pO1xyXG5cclxufSkodGhpcywgZnVuY3Rpb24oTG9uZykge1xyXG4gICAgXCJ1c2Ugc3RyaWN0XCI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb25zdHJ1Y3RzIGEgbmV3IEJ5dGVCdWZmZXIuXHJcbiAgICAgKiBAY2xhc3MgVGhlIHN3aXNzIGFybXkga25pZmUgZm9yIGJpbmFyeSBkYXRhIGluIEphdmFTY3JpcHQuXHJcbiAgICAgKiBAZXhwb3J0cyBCeXRlQnVmZmVyXHJcbiAgICAgKiBAY29uc3RydWN0b3JcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gY2FwYWNpdHkgSW5pdGlhbCBjYXBhY2l0eS4gRGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIuREVGQVVMVF9DQVBBQ0lUWX0uXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBsaXR0bGVFbmRpYW4gV2hldGhlciB0byB1c2UgbGl0dGxlIG9yIGJpZyBlbmRpYW4gYnl0ZSBvcmRlci4gRGVmYXVsdHMgdG9cclxuICAgICAqICB7QGxpbmsgQnl0ZUJ1ZmZlci5ERUZBVUxUX0VORElBTn0uXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBub0Fzc2VydCBXaGV0aGVyIHRvIHNraXAgYXNzZXJ0aW9ucyBvZiBvZmZzZXRzIGFuZCB2YWx1ZXMuIERlZmF1bHRzIHRvXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIuREVGQVVMVF9OT0FTU0VSVH0uXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIHZhciBCeXRlQnVmZmVyID0gZnVuY3Rpb24oY2FwYWNpdHksIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcclxuICAgICAgICBpZiAodHlwZW9mIGNhcGFjaXR5ID09PSAndW5kZWZpbmVkJylcclxuICAgICAgICAgICAgY2FwYWNpdHkgPSBCeXRlQnVmZmVyLkRFRkFVTFRfQ0FQQUNJVFk7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBsaXR0bGVFbmRpYW4gPT09ICd1bmRlZmluZWQnKVxyXG4gICAgICAgICAgICBsaXR0bGVFbmRpYW4gPSBCeXRlQnVmZmVyLkRFRkFVTFRfRU5ESUFOO1xyXG4gICAgICAgIGlmICh0eXBlb2Ygbm9Bc3NlcnQgPT09ICd1bmRlZmluZWQnKVxyXG4gICAgICAgICAgICBub0Fzc2VydCA9IEJ5dGVCdWZmZXIuREVGQVVMVF9OT0FTU0VSVDtcclxuICAgICAgICBpZiAoIW5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGNhcGFjaXR5ID0gY2FwYWNpdHkgfCAwO1xyXG4gICAgICAgICAgICBpZiAoY2FwYWNpdHkgPCAwKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgY2FwYWNpdHlcIik7XHJcbiAgICAgICAgICAgIGxpdHRsZUVuZGlhbiA9ICEhbGl0dGxlRW5kaWFuO1xyXG4gICAgICAgICAgICBub0Fzc2VydCA9ICEhbm9Bc3NlcnQ7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBCYWNraW5nIEFycmF5QnVmZmVyLlxyXG4gICAgICAgICAqIEB0eXBlIHshQXJyYXlCdWZmZXJ9XHJcbiAgICAgICAgICogQGV4cG9zZVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHRoaXMuYnVmZmVyID0gY2FwYWNpdHkgPT09IDAgPyBFTVBUWV9CVUZGRVIgOiBuZXcgQXJyYXlCdWZmZXIoY2FwYWNpdHkpO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBVaW50OEFycmF5IHV0aWxpemVkIHRvIG1hbmlwdWxhdGUgdGhlIGJhY2tpbmcgYnVmZmVyLiBCZWNvbWVzIGBudWxsYCBpZiB0aGUgYmFja2luZyBidWZmZXIgaGFzIGEgY2FwYWNpdHkgb2YgYDBgLlxyXG4gICAgICAgICAqIEB0eXBlIHs/VWludDhBcnJheX1cclxuICAgICAgICAgKiBAZXhwb3NlXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdGhpcy52aWV3ID0gY2FwYWNpdHkgPT09IDAgPyBudWxsIDogbmV3IFVpbnQ4QXJyYXkodGhpcy5idWZmZXIpO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBBYnNvbHV0ZSByZWFkL3dyaXRlIG9mZnNldC5cclxuICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfVxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKiBAc2VlIEJ5dGVCdWZmZXIjZmxpcFxyXG4gICAgICAgICAqIEBzZWUgQnl0ZUJ1ZmZlciNjbGVhclxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHRoaXMub2Zmc2V0ID0gMDtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogTWFya2VkIG9mZnNldC5cclxuICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfVxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKiBAc2VlIEJ5dGVCdWZmZXIjbWFya1xyXG4gICAgICAgICAqIEBzZWUgQnl0ZUJ1ZmZlciNyZXNldFxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHRoaXMubWFya2VkT2Zmc2V0ID0gLTE7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIEFic29sdXRlIGxpbWl0IG9mIHRoZSBjb250YWluZWQgZGF0YS4gU2V0IHRvIHRoZSBiYWNraW5nIGJ1ZmZlcidzIGNhcGFjaXR5IHVwb24gYWxsb2NhdGlvbi5cclxuICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfVxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKiBAc2VlIEJ5dGVCdWZmZXIjZmxpcFxyXG4gICAgICAgICAqIEBzZWUgQnl0ZUJ1ZmZlciNjbGVhclxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHRoaXMubGltaXQgPSBjYXBhY2l0eTtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogV2hldGhlciB0byB1c2UgbGl0dGxlIGVuZGlhbiBieXRlIG9yZGVyLCBkZWZhdWx0cyB0byBgZmFsc2VgIGZvciBiaWcgZW5kaWFuLlxyXG4gICAgICAgICAqIEB0eXBlIHtib29sZWFufVxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKi9cclxuICAgICAgICB0aGlzLmxpdHRsZUVuZGlhbiA9IGxpdHRsZUVuZGlhbjtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogV2hldGhlciB0byBza2lwIGFzc2VydGlvbnMgb2Ygb2Zmc2V0cyBhbmQgdmFsdWVzLCBkZWZhdWx0cyB0byBgZmFsc2VgLlxyXG4gICAgICAgICAqIEB0eXBlIHtib29sZWFufVxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKi9cclxuICAgICAgICB0aGlzLm5vQXNzZXJ0ID0gbm9Bc3NlcnQ7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQnl0ZUJ1ZmZlciB2ZXJzaW9uLlxyXG4gICAgICogQHR5cGUge3N0cmluZ31cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLlZFUlNJT04gPSBcIjUuMC4xXCI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMaXR0bGUgZW5kaWFuIGNvbnN0YW50IHRoYXQgY2FuIGJlIHVzZWQgaW5zdGVhZCBvZiBpdHMgYm9vbGVhbiB2YWx1ZS4gRXZhbHVhdGVzIHRvIGB0cnVlYC5cclxuICAgICAqIEB0eXBlIHtib29sZWFufVxyXG4gICAgICogQGNvbnN0XHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuTElUVExFX0VORElBTiA9IHRydWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBCaWcgZW5kaWFuIGNvbnN0YW50IHRoYXQgY2FuIGJlIHVzZWQgaW5zdGVhZCBvZiBpdHMgYm9vbGVhbiB2YWx1ZS4gRXZhbHVhdGVzIHRvIGBmYWxzZWAuXHJcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLkJJR19FTkRJQU4gPSBmYWxzZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmF1bHQgaW5pdGlhbCBjYXBhY2l0eSBvZiBgMTZgLlxyXG4gICAgICogQHR5cGUge251bWJlcn1cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlci5ERUZBVUxUX0NBUEFDSVRZID0gMTY7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZhdWx0IGVuZGlhbmVzcyBvZiBgZmFsc2VgIGZvciBiaWcgZW5kaWFuLlxyXG4gICAgICogQHR5cGUge2Jvb2xlYW59XHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuREVGQVVMVF9FTkRJQU4gPSBCeXRlQnVmZmVyLkJJR19FTkRJQU47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZhdWx0IG5vIGFzc2VydGlvbnMgZmxhZyBvZiBgZmFsc2VgLlxyXG4gICAgICogQHR5cGUge2Jvb2xlYW59XHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuREVGQVVMVF9OT0FTU0VSVCA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQSBgTG9uZ2AgY2xhc3MgZm9yIHJlcHJlc2VudGluZyBhIDY0LWJpdCB0d28ncy1jb21wbGVtZW50IGludGVnZXIgdmFsdWUuIE1heSBiZSBgbnVsbGAgaWYgTG9uZy5qcyBoYXMgbm90IGJlZW4gbG9hZGVkXHJcbiAgICAgKiAgYW5kIGludDY0IHN1cHBvcnQgaXMgbm90IGF2YWlsYWJsZS5cclxuICAgICAqIEB0eXBlIHs/TG9uZ31cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQHNlZSBodHRwczovL2dpdGh1Yi5jb20vZGNvZGVJTy9sb25nLmpzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuTG9uZyA9IExvbmcgfHwgbnVsbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBhbGlhcyBCeXRlQnVmZmVyLnByb3RvdHlwZVxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIHZhciBCeXRlQnVmZmVyUHJvdG90eXBlID0gQnl0ZUJ1ZmZlci5wcm90b3R5cGU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBbiBpbmRpY2F0b3IgdXNlZCB0byByZWxpYWJseSBkZXRlcm1pbmUgaWYgYW4gb2JqZWN0IGlzIGEgQnl0ZUJ1ZmZlciBvciBub3QuXHJcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICogQHByaXZhdGVcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5fX2lzQnl0ZUJ1ZmZlcl9fO1xyXG5cclxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShCeXRlQnVmZmVyUHJvdG90eXBlLCBcIl9faXNCeXRlQnVmZmVyX19cIiwge1xyXG4gICAgICAgIHZhbHVlOiB0cnVlLFxyXG4gICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxyXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogZmFsc2VcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIGhlbHBlcnNcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHshQXJyYXlCdWZmZXJ9XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIEVNUFRZX0JVRkZFUiA9IG5ldyBBcnJheUJ1ZmZlcigwKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFN0cmluZy5mcm9tQ2hhckNvZGUgcmVmZXJlbmNlIGZvciBjb21waWxlLXRpbWUgcmVuYW1pbmcuXHJcbiAgICAgKiBAdHlwZSB7ZnVuY3Rpb24oLi4ubnVtYmVyKTpzdHJpbmd9XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIHN0cmluZ0Zyb21DaGFyQ29kZSA9IFN0cmluZy5mcm9tQ2hhckNvZGU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGEgc291cmNlIGZ1bmN0aW9uIGZvciBhIHN0cmluZy5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzIFN0cmluZyB0byByZWFkIGZyb21cclxuICAgICAqIEByZXR1cm5zIHtmdW5jdGlvbigpOm51bWJlcnxudWxsfSBTb3VyY2UgZnVuY3Rpb24gcmV0dXJuaW5nIHRoZSBuZXh0IGNoYXIgY29kZSByZXNwZWN0aXZlbHkgYG51bGxgIGlmIHRoZXJlIGFyZVxyXG4gICAgICogIG5vIG1vcmUgY2hhcmFjdGVycyBsZWZ0LlxyXG4gICAgICogQHRocm93cyB7VHlwZUVycm9yfSBJZiB0aGUgYXJndW1lbnQgaXMgaW52YWxpZFxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIGZ1bmN0aW9uIHN0cmluZ1NvdXJjZShzKSB7XHJcbiAgICAgICAgdmFyIGk9MDsgcmV0dXJuIGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gaSA8IHMubGVuZ3RoID8gcy5jaGFyQ29kZUF0KGkrKykgOiBudWxsO1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGEgZGVzdGluYXRpb24gZnVuY3Rpb24gZm9yIGEgc3RyaW5nLlxyXG4gICAgICogQHJldHVybnMge2Z1bmN0aW9uKG51bWJlcj0pOnVuZGVmaW5lZHxzdHJpbmd9IERlc3RpbmF0aW9uIGZ1bmN0aW9uIHN1Y2Nlc3NpdmVseSBjYWxsZWQgd2l0aCB0aGUgbmV4dCBjaGFyIGNvZGUuXHJcbiAgICAgKiAgUmV0dXJucyB0aGUgZmluYWwgc3RyaW5nIHdoZW4gY2FsbGVkIHdpdGhvdXQgYXJndW1lbnRzLlxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIGZ1bmN0aW9uIHN0cmluZ0Rlc3RpbmF0aW9uKCkge1xyXG4gICAgICAgIHZhciBjcyA9IFtdLCBwcyA9IFtdOyByZXR1cm4gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgICAgIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBzLmpvaW4oJycpK3N0cmluZ0Zyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIGNzKTtcclxuICAgICAgICAgICAgaWYgKGNzLmxlbmd0aCArIGFyZ3VtZW50cy5sZW5ndGggPiAxMDI0KVxyXG4gICAgICAgICAgICAgICAgcHMucHVzaChzdHJpbmdGcm9tQ2hhckNvZGUuYXBwbHkoU3RyaW5nLCBjcykpLFxyXG4gICAgICAgICAgICAgICAgICAgIGNzLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGNzLCBhcmd1bWVudHMpO1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBhY2Nlc3NvciB0eXBlLlxyXG4gICAgICogQHJldHVybnMge0Z1bmN0aW9ufSBgQnVmZmVyYCB1bmRlciBub2RlLmpzLCBgVWludDhBcnJheWAgcmVzcGVjdGl2ZWx5IGBEYXRhVmlld2AgaW4gdGhlIGJyb3dzZXIgKGNsYXNzZXMpXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuYWNjZXNzb3IgPSBmdW5jdGlvbigpIHtcclxuICAgICAgICByZXR1cm4gVWludDhBcnJheTtcclxuICAgIH07XHJcbiAgICAvKipcclxuICAgICAqIEFsbG9jYXRlcyBhIG5ldyBCeXRlQnVmZmVyIGJhY2tlZCBieSBhIGJ1ZmZlciBvZiB0aGUgc3BlY2lmaWVkIGNhcGFjaXR5LlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBjYXBhY2l0eSBJbml0aWFsIGNhcGFjaXR5LiBEZWZhdWx0cyB0byB7QGxpbmsgQnl0ZUJ1ZmZlci5ERUZBVUxUX0NBUEFDSVRZfS5cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IGxpdHRsZUVuZGlhbiBXaGV0aGVyIHRvIHVzZSBsaXR0bGUgb3IgYmlnIGVuZGlhbiBieXRlIG9yZGVyLiBEZWZhdWx0cyB0b1xyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyLkRFRkFVTFRfRU5ESUFOfS5cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IG5vQXNzZXJ0IFdoZXRoZXIgdG8gc2tpcCBhc3NlcnRpb25zIG9mIG9mZnNldHMgYW5kIHZhbHVlcy4gRGVmYXVsdHMgdG9cclxuICAgICAqICB7QGxpbmsgQnl0ZUJ1ZmZlci5ERUZBVUxUX05PQVNTRVJUfS5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn1cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlci5hbGxvY2F0ZSA9IGZ1bmN0aW9uKGNhcGFjaXR5LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBCeXRlQnVmZmVyKGNhcGFjaXR5LCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb25jYXRlbmF0ZXMgbXVsdGlwbGUgQnl0ZUJ1ZmZlcnMgaW50byBvbmUuXHJcbiAgICAgKiBAcGFyYW0geyFBcnJheS48IUJ5dGVCdWZmZXJ8IUFycmF5QnVmZmVyfCFVaW50OEFycmF5fHN0cmluZz59IGJ1ZmZlcnMgQnVmZmVycyB0byBjb25jYXRlbmF0ZVxyXG4gICAgICogQHBhcmFtIHsoc3RyaW5nfGJvb2xlYW4pPX0gZW5jb2RpbmcgU3RyaW5nIGVuY29kaW5nIGlmIGBidWZmZXJzYCBjb250YWlucyBhIHN0cmluZyAoXCJiYXNlNjRcIiwgXCJoZXhcIiwgXCJiaW5hcnlcIixcclxuICAgICAqICBkZWZhdWx0cyB0byBcInV0ZjhcIilcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IGxpdHRsZUVuZGlhbiBXaGV0aGVyIHRvIHVzZSBsaXR0bGUgb3IgYmlnIGVuZGlhbiBieXRlIG9yZGVyIGZvciB0aGUgcmVzdWx0aW5nIEJ5dGVCdWZmZXIuIERlZmF1bHRzXHJcbiAgICAgKiAgdG8ge0BsaW5rIEJ5dGVCdWZmZXIuREVGQVVMVF9FTkRJQU59LlxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gbm9Bc3NlcnQgV2hldGhlciB0byBza2lwIGFzc2VydGlvbnMgb2Ygb2Zmc2V0cyBhbmQgdmFsdWVzIGZvciB0aGUgcmVzdWx0aW5nIEJ5dGVCdWZmZXIuIERlZmF1bHRzIHRvXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIuREVGQVVMVF9OT0FTU0VSVH0uXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IENvbmNhdGVuYXRlZCBCeXRlQnVmZmVyXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuY29uY2F0ID0gZnVuY3Rpb24oYnVmZmVycywgZW5jb2RpbmcsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpIHtcclxuICAgICAgICBpZiAodHlwZW9mIGVuY29kaW5nID09PSAnYm9vbGVhbicgfHwgdHlwZW9mIGVuY29kaW5nICE9PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICBub0Fzc2VydCA9IGxpdHRsZUVuZGlhbjtcclxuICAgICAgICAgICAgbGl0dGxlRW5kaWFuID0gZW5jb2Rpbmc7XHJcbiAgICAgICAgICAgIGVuY29kaW5nID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgY2FwYWNpdHkgPSAwO1xyXG4gICAgICAgIGZvciAodmFyIGk9MCwgaz1idWZmZXJzLmxlbmd0aCwgbGVuZ3RoOyBpPGs7ICsraSkge1xyXG4gICAgICAgICAgICBpZiAoIUJ5dGVCdWZmZXIuaXNCeXRlQnVmZmVyKGJ1ZmZlcnNbaV0pKVxyXG4gICAgICAgICAgICAgICAgYnVmZmVyc1tpXSA9IEJ5dGVCdWZmZXIud3JhcChidWZmZXJzW2ldLCBlbmNvZGluZyk7XHJcbiAgICAgICAgICAgIGxlbmd0aCA9IGJ1ZmZlcnNbaV0ubGltaXQgLSBidWZmZXJzW2ldLm9mZnNldDtcclxuICAgICAgICAgICAgaWYgKGxlbmd0aCA+IDApIGNhcGFjaXR5ICs9IGxlbmd0aDtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGNhcGFjaXR5ID09PSAwKVxyXG4gICAgICAgICAgICByZXR1cm4gbmV3IEJ5dGVCdWZmZXIoMCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCk7XHJcbiAgICAgICAgdmFyIGJiID0gbmV3IEJ5dGVCdWZmZXIoY2FwYWNpdHksIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpLFxyXG4gICAgICAgICAgICBiaTtcclxuICAgICAgICBpPTA7IHdoaWxlIChpPGspIHtcclxuICAgICAgICAgICAgYmkgPSBidWZmZXJzW2krK107XHJcbiAgICAgICAgICAgIGxlbmd0aCA9IGJpLmxpbWl0IC0gYmkub2Zmc2V0O1xyXG4gICAgICAgICAgICBpZiAobGVuZ3RoIDw9IDApIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICBiYi52aWV3LnNldChiaS52aWV3LnN1YmFycmF5KGJpLm9mZnNldCwgYmkubGltaXQpLCBiYi5vZmZzZXQpO1xyXG4gICAgICAgICAgICBiYi5vZmZzZXQgKz0gbGVuZ3RoO1xyXG4gICAgICAgIH1cclxuICAgICAgICBiYi5saW1pdCA9IGJiLm9mZnNldDtcclxuICAgICAgICBiYi5vZmZzZXQgPSAwO1xyXG4gICAgICAgIHJldHVybiBiYjtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXN0cyBpZiB0aGUgc3BlY2lmaWVkIHR5cGUgaXMgYSBCeXRlQnVmZmVyLlxyXG4gICAgICogQHBhcmFtIHsqfSBiYiBCeXRlQnVmZmVyIHRvIHRlc3RcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufSBgdHJ1ZWAgaWYgaXQgaXMgYSBCeXRlQnVmZmVyLCBvdGhlcndpc2UgYGZhbHNlYFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLmlzQnl0ZUJ1ZmZlciA9IGZ1bmN0aW9uKGJiKSB7XHJcbiAgICAgICAgcmV0dXJuIChiYiAmJiBiYltcIl9faXNCeXRlQnVmZmVyX19cIl0pID09PSB0cnVlO1xyXG4gICAgfTtcclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgYmFja2luZyBidWZmZXIgdHlwZS5cclxuICAgICAqIEByZXR1cm5zIHtGdW5jdGlvbn0gYEJ1ZmZlcmAgdW5kZXIgbm9kZS5qcywgYEFycmF5QnVmZmVyYCBpbiB0aGUgYnJvd3NlciAoY2xhc3NlcylcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlci50eXBlID0gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgcmV0dXJuIEFycmF5QnVmZmVyO1xyXG4gICAgfTtcclxuICAgIC8qKlxyXG4gICAgICogV3JhcHMgYSBidWZmZXIgb3IgYSBzdHJpbmcuIFNldHMgdGhlIGFsbG9jYXRlZCBCeXRlQnVmZmVyJ3Mge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSB0byBgMGAgYW5kIGl0c1xyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyI2xpbWl0fSB0byB0aGUgbGVuZ3RoIG9mIHRoZSB3cmFwcGVkIGRhdGEuXHJcbiAgICAgKiBAcGFyYW0geyFCeXRlQnVmZmVyfCFBcnJheUJ1ZmZlcnwhVWludDhBcnJheXxzdHJpbmd8IUFycmF5LjxudW1iZXI+fSBidWZmZXIgQW55dGhpbmcgdGhhdCBjYW4gYmUgd3JhcHBlZFxyXG4gICAgICogQHBhcmFtIHsoc3RyaW5nfGJvb2xlYW4pPX0gZW5jb2RpbmcgU3RyaW5nIGVuY29kaW5nIGlmIGBidWZmZXJgIGlzIGEgc3RyaW5nIChcImJhc2U2NFwiLCBcImhleFwiLCBcImJpbmFyeVwiLCBkZWZhdWx0cyB0b1xyXG4gICAgICogIFwidXRmOFwiKVxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gbGl0dGxlRW5kaWFuIFdoZXRoZXIgdG8gdXNlIGxpdHRsZSBvciBiaWcgZW5kaWFuIGJ5dGUgb3JkZXIuIERlZmF1bHRzIHRvXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIuREVGQVVMVF9FTkRJQU59LlxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gbm9Bc3NlcnQgV2hldGhlciB0byBza2lwIGFzc2VydGlvbnMgb2Ygb2Zmc2V0cyBhbmQgdmFsdWVzLiBEZWZhdWx0cyB0b1xyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyLkRFRkFVTFRfTk9BU1NFUlR9LlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSBBIEJ5dGVCdWZmZXIgd3JhcHBpbmcgYGJ1ZmZlcmBcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlci53cmFwID0gZnVuY3Rpb24oYnVmZmVyLCBlbmNvZGluZywgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgZW5jb2RpbmcgIT09ICdzdHJpbmcnKSB7XHJcbiAgICAgICAgICAgIG5vQXNzZXJ0ID0gbGl0dGxlRW5kaWFuO1xyXG4gICAgICAgICAgICBsaXR0bGVFbmRpYW4gPSBlbmNvZGluZztcclxuICAgICAgICAgICAgZW5jb2RpbmcgPSB1bmRlZmluZWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0eXBlb2YgYnVmZmVyID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIGVuY29kaW5nID09PSAndW5kZWZpbmVkJylcclxuICAgICAgICAgICAgICAgIGVuY29kaW5nID0gXCJ1dGY4XCI7XHJcbiAgICAgICAgICAgIHN3aXRjaCAoZW5jb2RpbmcpIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgXCJiYXNlNjRcIjpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gQnl0ZUJ1ZmZlci5mcm9tQmFzZTY0KGJ1ZmZlciwgbGl0dGxlRW5kaWFuKTtcclxuICAgICAgICAgICAgICAgIGNhc2UgXCJoZXhcIjpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gQnl0ZUJ1ZmZlci5mcm9tSGV4KGJ1ZmZlciwgbGl0dGxlRW5kaWFuKTtcclxuICAgICAgICAgICAgICAgIGNhc2UgXCJiaW5hcnlcIjpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gQnl0ZUJ1ZmZlci5mcm9tQmluYXJ5KGJ1ZmZlciwgbGl0dGxlRW5kaWFuKTtcclxuICAgICAgICAgICAgICAgIGNhc2UgXCJ1dGY4XCI6XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEJ5dGVCdWZmZXIuZnJvbVVURjgoYnVmZmVyLCBsaXR0bGVFbmRpYW4pO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBcImRlYnVnXCI6XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEJ5dGVCdWZmZXIuZnJvbURlYnVnKGJ1ZmZlciwgbGl0dGxlRW5kaWFuKTtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgRXJyb3IoXCJVbnN1cHBvcnRlZCBlbmNvZGluZzogXCIrZW5jb2RpbmcpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChidWZmZXIgPT09IG51bGwgfHwgdHlwZW9mIGJ1ZmZlciAhPT0gJ29iamVjdCcpXHJcbiAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgYnVmZmVyXCIpO1xyXG4gICAgICAgIHZhciBiYjtcclxuICAgICAgICBpZiAoQnl0ZUJ1ZmZlci5pc0J5dGVCdWZmZXIoYnVmZmVyKSkge1xyXG4gICAgICAgICAgICBiYiA9IEJ5dGVCdWZmZXJQcm90b3R5cGUuY2xvbmUuY2FsbChidWZmZXIpO1xyXG4gICAgICAgICAgICBiYi5tYXJrZWRPZmZzZXQgPSAtMTtcclxuICAgICAgICAgICAgcmV0dXJuIGJiO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoYnVmZmVyIGluc3RhbmNlb2YgVWludDhBcnJheSkgeyAvLyBFeHRyYWN0IEFycmF5QnVmZmVyIGZyb20gVWludDhBcnJheVxyXG4gICAgICAgICAgICBiYiA9IG5ldyBCeXRlQnVmZmVyKDAsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpO1xyXG4gICAgICAgICAgICBpZiAoYnVmZmVyLmxlbmd0aCA+IDApIHsgLy8gQXZvaWQgcmVmZXJlbmNlcyB0byBtb3JlIHRoYW4gb25lIEVNUFRZX0JVRkZFUlxyXG4gICAgICAgICAgICAgICAgYmIuYnVmZmVyID0gYnVmZmVyLmJ1ZmZlcjtcclxuICAgICAgICAgICAgICAgIGJiLm9mZnNldCA9IGJ1ZmZlci5ieXRlT2Zmc2V0O1xyXG4gICAgICAgICAgICAgICAgYmIubGltaXQgPSBidWZmZXIuYnl0ZU9mZnNldCArIGJ1ZmZlci5ieXRlTGVuZ3RoO1xyXG4gICAgICAgICAgICAgICAgYmIudmlldyA9IG5ldyBVaW50OEFycmF5KGJ1ZmZlci5idWZmZXIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmIChidWZmZXIgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikgeyAvLyBSZXVzZSBBcnJheUJ1ZmZlclxyXG4gICAgICAgICAgICBiYiA9IG5ldyBCeXRlQnVmZmVyKDAsIGxpdHRsZUVuZGlhbiwgbm9Bc3NlcnQpO1xyXG4gICAgICAgICAgICBpZiAoYnVmZmVyLmJ5dGVMZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICBiYi5idWZmZXIgPSBidWZmZXI7XHJcbiAgICAgICAgICAgICAgICBiYi5vZmZzZXQgPSAwO1xyXG4gICAgICAgICAgICAgICAgYmIubGltaXQgPSBidWZmZXIuYnl0ZUxlbmd0aDtcclxuICAgICAgICAgICAgICAgIGJiLnZpZXcgPSBidWZmZXIuYnl0ZUxlbmd0aCA+IDAgPyBuZXcgVWludDhBcnJheShidWZmZXIpIDogbnVsbDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSBpZiAoT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGJ1ZmZlcikgPT09IFwiW29iamVjdCBBcnJheV1cIikgeyAvLyBDcmVhdGUgZnJvbSBvY3RldHNcclxuICAgICAgICAgICAgYmIgPSBuZXcgQnl0ZUJ1ZmZlcihidWZmZXIubGVuZ3RoLCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KTtcclxuICAgICAgICAgICAgYmIubGltaXQgPSBidWZmZXIubGVuZ3RoO1xyXG4gICAgICAgICAgICBmb3IgKHZhciBpPTA7IGk8YnVmZmVyLmxlbmd0aDsgKytpKVxyXG4gICAgICAgICAgICAgICAgYmIudmlld1tpXSA9IGJ1ZmZlcltpXTtcclxuICAgICAgICB9IGVsc2VcclxuICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBidWZmZXJcIik7IC8vIE90aGVyd2lzZSBmYWlsXHJcbiAgICAgICAgcmV0dXJuIGJiO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdyaXRlcyB0aGUgYXJyYXkgYXMgYSBiaXRzZXQuXHJcbiAgICAgKiBAcGFyYW0ge0FycmF5PGJvb2xlYW4+fSB2YWx1ZSBBcnJheSBvZiBib29sZWFucyB0byB3cml0ZVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYGxlbmd0aGAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn1cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZUJpdFNldCA9IGZ1bmN0aW9uKHZhbHVlLCBvZmZzZXQpIHtcclxuICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgaWYgKCEodmFsdWUgaW5zdGFuY2VvZiBBcnJheSkpXHJcbiAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIEJpdFNldDogTm90IGFuIGFycmF5XCIpO1xyXG4gICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIiswK1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgIH1cclxuXHJcbiAgICAgIHZhciBzdGFydCA9IG9mZnNldCxcclxuICAgICAgICAgIGJpdHMgPSB2YWx1ZS5sZW5ndGgsXHJcbiAgICAgICAgICBieXRlcyA9IChiaXRzID4+IDMpLFxyXG4gICAgICAgICAgYml0ID0gMCxcclxuICAgICAgICAgIGs7XHJcblxyXG4gICAgICBvZmZzZXQgKz0gdGhpcy53cml0ZVZhcmludDMyKGJpdHMsb2Zmc2V0KTtcclxuXHJcbiAgICAgIHdoaWxlKGJ5dGVzLS0pIHtcclxuICAgICAgICBrID0gKCEhdmFsdWVbYml0KytdICYgMSkgfFxyXG4gICAgICAgICAgICAoKCEhdmFsdWVbYml0KytdICYgMSkgPDwgMSkgfFxyXG4gICAgICAgICAgICAoKCEhdmFsdWVbYml0KytdICYgMSkgPDwgMikgfFxyXG4gICAgICAgICAgICAoKCEhdmFsdWVbYml0KytdICYgMSkgPDwgMykgfFxyXG4gICAgICAgICAgICAoKCEhdmFsdWVbYml0KytdICYgMSkgPDwgNCkgfFxyXG4gICAgICAgICAgICAoKCEhdmFsdWVbYml0KytdICYgMSkgPDwgNSkgfFxyXG4gICAgICAgICAgICAoKCEhdmFsdWVbYml0KytdICYgMSkgPDwgNikgfFxyXG4gICAgICAgICAgICAoKCEhdmFsdWVbYml0KytdICYgMSkgPDwgNyk7XHJcbiAgICAgICAgdGhpcy53cml0ZUJ5dGUoayxvZmZzZXQrKyk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGlmKGJpdCA8IGJpdHMpIHtcclxuICAgICAgICB2YXIgbSA9IDA7IGsgPSAwO1xyXG4gICAgICAgIHdoaWxlKGJpdCA8IGJpdHMpIGsgPSBrIHwgKCghIXZhbHVlW2JpdCsrXSAmIDEpIDw8IChtKyspKTtcclxuICAgICAgICB0aGlzLndyaXRlQnl0ZShrLG9mZnNldCsrKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHJlbGF0aXZlKSB7XHJcbiAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIG9mZnNldCAtIHN0YXJ0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYSBCaXRTZXQgYXMgYW4gYXJyYXkgb2YgYm9vbGVhbnMuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgbGVuZ3RoYCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMge0FycmF5PGJvb2xlYW4+XHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZEJpdFNldCA9IGZ1bmN0aW9uKG9mZnNldCkge1xyXG4gICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG5cclxuICAgICAgdmFyIHJldCA9IHRoaXMucmVhZFZhcmludDMyKG9mZnNldCksXHJcbiAgICAgICAgICBiaXRzID0gcmV0LnZhbHVlLFxyXG4gICAgICAgICAgYnl0ZXMgPSAoYml0cyA+PiAzKSxcclxuICAgICAgICAgIGJpdCA9IDAsXHJcbiAgICAgICAgICB2YWx1ZSA9IFtdLFxyXG4gICAgICAgICAgaztcclxuXHJcbiAgICAgIG9mZnNldCArPSByZXQubGVuZ3RoO1xyXG5cclxuICAgICAgd2hpbGUoYnl0ZXMtLSkge1xyXG4gICAgICAgIGsgPSB0aGlzLnJlYWRCeXRlKG9mZnNldCsrKTtcclxuICAgICAgICB2YWx1ZVtiaXQrK10gPSAhIShrICYgMHgwMSk7XHJcbiAgICAgICAgdmFsdWVbYml0KytdID0gISEoayAmIDB4MDIpO1xyXG4gICAgICAgIHZhbHVlW2JpdCsrXSA9ICEhKGsgJiAweDA0KTtcclxuICAgICAgICB2YWx1ZVtiaXQrK10gPSAhIShrICYgMHgwOCk7XHJcbiAgICAgICAgdmFsdWVbYml0KytdID0gISEoayAmIDB4MTApO1xyXG4gICAgICAgIHZhbHVlW2JpdCsrXSA9ICEhKGsgJiAweDIwKTtcclxuICAgICAgICB2YWx1ZVtiaXQrK10gPSAhIShrICYgMHg0MCk7XHJcbiAgICAgICAgdmFsdWVbYml0KytdID0gISEoayAmIDB4ODApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZihiaXQgPCBiaXRzKSB7XHJcbiAgICAgICAgdmFyIG0gPSAwO1xyXG4gICAgICAgIGsgPSB0aGlzLnJlYWRCeXRlKG9mZnNldCsrKTtcclxuICAgICAgICB3aGlsZShiaXQgPCBiaXRzKSB2YWx1ZVtiaXQrK10gPSAhISgoayA+PiAobSsrKSkgJiAxKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgaWYgKHJlbGF0aXZlKSB7XHJcbiAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfVxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyB0aGUgc3BlY2lmaWVkIG51bWJlciBvZiBieXRlcy5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBsZW5ndGggTnVtYmVyIG9mIGJ5dGVzIHRvIHJlYWRcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byByZWFkIGZyb20uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGBsZW5ndGhgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9XHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZEJ5dGVzID0gZnVuY3Rpb24obGVuZ3RoLCBvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyBsZW5ndGggPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIitsZW5ndGgrXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHNsaWNlID0gdGhpcy5zbGljZShvZmZzZXQsIG9mZnNldCArIGxlbmd0aCk7XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB0aGlzLm9mZnNldCArPSBsZW5ndGg7XG4gICAgICAgIHJldHVybiBzbGljZTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYSBwYXlsb2FkIG9mIGJ5dGVzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBCeXRlQnVmZmVyI2FwcGVuZH0uXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7IUJ5dGVCdWZmZXJ8IUFycmF5QnVmZmVyfCFVaW50OEFycmF5fHN0cmluZ30gc291cmNlIERhdGEgdG8gd3JpdGUuIElmIGBzb3VyY2VgIGlzIGEgQnl0ZUJ1ZmZlciwgaXRzIG9mZnNldHNcclxuICAgICAqICB3aWxsIGJlIG1vZGlmaWVkIGFjY29yZGluZyB0byB0aGUgcGVyZm9ybWVkIHJlYWQgb3BlcmF0aW9uLlxyXG4gICAgICogQHBhcmFtIHsoc3RyaW5nfG51bWJlcik9fSBlbmNvZGluZyBFbmNvZGluZyBpZiBgZGF0YWAgaXMgYSBzdHJpbmcgKFwiYmFzZTY0XCIsIFwiaGV4XCIsIFwiYmluYXJ5XCIsIGRlZmF1bHRzIHRvIFwidXRmOFwiKVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHdyaXRlIHRvLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSB0aGUgbnVtYmVyIG9mIGJ5dGVzXHJcbiAgICAgKiAgd3JpdHRlbiBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVCeXRlcyA9IEJ5dGVCdWZmZXJQcm90b3R5cGUuYXBwZW5kO1xyXG5cclxuICAgIC8vIHR5cGVzL2ludHMvaW50OFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGFuIDhiaXQgc2lnbmVkIGludGVnZXIuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgMWAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlSW50OCA9IGZ1bmN0aW9uKHZhbHVlLCBvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIHZhbHVlOiBcIit2YWx1ZStcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgdmFsdWUgfD0gMDtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICBvZmZzZXQgKz0gMTtcbiAgICAgICAgdmFyIGNhcGFjaXR5MCA9IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICAgIGlmIChvZmZzZXQgPiBjYXBhY2l0eTApXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZSgoY2FwYWNpdHkwICo9IDIpID4gb2Zmc2V0ID8gY2FwYWNpdHkwIDogb2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0IC09IDE7XG4gICAgICAgIHRoaXMudmlld1tvZmZzZXRdID0gdmFsdWU7XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB0aGlzLm9mZnNldCArPSAxO1xuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYW4gOGJpdCBzaWduZWQgaW50ZWdlci4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlciN3cml0ZUludDh9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgMWAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlQnl0ZSA9IEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVJbnQ4O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYW4gOGJpdCBzaWduZWQgaW50ZWdlci5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byByZWFkIGZyb20uIFdpbGwgdXNlIGFuZCBhZHZhbmNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDFgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZEludDggPSBmdW5jdGlvbihvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAxID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMStcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLnZpZXdbb2Zmc2V0XTtcclxuICAgICAgICBpZiAoKHZhbHVlICYgMHg4MCkgPT09IDB4ODApIHZhbHVlID0gLSgweEZGIC0gdmFsdWUgKyAxKTsgLy8gQ2FzdCB0byBzaWduZWRcclxuICAgICAgICBpZiAocmVsYXRpdmUpIHRoaXMub2Zmc2V0ICs9IDE7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhbiA4Yml0IHNpZ25lZCBpbnRlZ2VyLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBCeXRlQnVmZmVyI3JlYWRJbnQ4fS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgMWAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkQnl0ZSA9IEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZEludDg7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYW4gOGJpdCB1bnNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBhZHZhbmNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDFgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVVpbnQ4ID0gZnVuY3Rpb24odmFsdWUsIG9mZnNldCkge1xyXG4gICAgICAgIHZhciByZWxhdGl2ZSA9IHR5cGVvZiBvZmZzZXQgPT09ICd1bmRlZmluZWQnO1xuICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicgfHwgdmFsdWUgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgdmFsdWU6IFwiK3ZhbHVlK1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICB2YWx1ZSA+Pj49IDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzArXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgb2Zmc2V0ICs9IDE7XG4gICAgICAgIHZhciBjYXBhY2l0eTEgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAob2Zmc2V0ID4gY2FwYWNpdHkxKVxuICAgICAgICAgICAgdGhpcy5yZXNpemUoKGNhcGFjaXR5MSAqPSAyKSA+IG9mZnNldCA/IGNhcGFjaXR5MSA6IG9mZnNldCk7XG4gICAgICAgIG9mZnNldCAtPSAxO1xuICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0XSA9IHZhbHVlO1xyXG4gICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGFuIDhiaXQgdW5zaWduZWQgaW50ZWdlci4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlciN3cml0ZVVpbnQ4fS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBhZHZhbmNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDFgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVVJbnQ4ID0gQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVVpbnQ4O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYW4gOGJpdCB1bnNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgMWAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVWludDggPSBmdW5jdGlvbihvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAxID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMStcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICB2YXIgdmFsdWUgPSB0aGlzLnZpZXdbb2Zmc2V0XTtcclxuICAgICAgICBpZiAocmVsYXRpdmUpIHRoaXMub2Zmc2V0ICs9IDE7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhbiA4Yml0IHVuc2lnbmVkIGludGVnZXIuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIEJ5dGVCdWZmZXIjcmVhZFVpbnQ4fS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgMWAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVUludDggPSBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWRVaW50ODtcclxuXHJcbiAgICAvLyB0eXBlcy9pbnRzL2ludDE2XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYSAxNmJpdCBzaWduZWQgaW50ZWdlci5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHdyaXRlIHRvLiBXaWxsIHVzZSBhbmQgYWR2YW5jZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGAyYCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHRocm93cyB7VHlwZUVycm9yfSBJZiBgb2Zmc2V0YCBvciBgdmFsdWVgIGlzIG5vdCBhIHZhbGlkIG51bWJlclxyXG4gICAgICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYG9mZnNldGAgaXMgb3V0IG9mIGJvdW5kc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlSW50MTYgPSBmdW5jdGlvbih2YWx1ZSwgb2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyB8fCB2YWx1ZSAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCB2YWx1ZTogXCIrdmFsdWUrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIHZhbHVlIHw9IDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzArXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgb2Zmc2V0ICs9IDI7XG4gICAgICAgIHZhciBjYXBhY2l0eTIgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAob2Zmc2V0ID4gY2FwYWNpdHkyKVxuICAgICAgICAgICAgdGhpcy5yZXNpemUoKGNhcGFjaXR5MiAqPSAyKSA+IG9mZnNldCA/IGNhcGFjaXR5MiA6IG9mZnNldCk7XG4gICAgICAgIG9mZnNldCAtPSAyO1xuICAgICAgICBpZiAodGhpcy5saXR0bGVFbmRpYW4pIHtcclxuICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsxXSA9ICh2YWx1ZSAmIDB4RkYwMCkgPj4+IDg7XHJcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQgIF0gPSAgdmFsdWUgJiAweDAwRkY7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldF0gICA9ICh2YWx1ZSAmIDB4RkYwMCkgPj4+IDg7XHJcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrMV0gPSAgdmFsdWUgJiAweDAwRkY7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gMjtcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGEgMTZiaXQgc2lnbmVkIGludGVnZXIuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIEJ5dGVCdWZmZXIjd3JpdGVJbnQxNn0uXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHdyaXRlIHRvLiBXaWxsIHVzZSBhbmQgYWR2YW5jZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGAyYCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHRocm93cyB7VHlwZUVycm9yfSBJZiBgb2Zmc2V0YCBvciBgdmFsdWVgIGlzIG5vdCBhIHZhbGlkIG51bWJlclxyXG4gICAgICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYG9mZnNldGAgaXMgb3V0IG9mIGJvdW5kc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlU2hvcnQgPSBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlSW50MTY7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIDE2Yml0IHNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgMmAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICAgICAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gSWYgYG9mZnNldGAgaXMgbm90IGEgdmFsaWQgbnVtYmVyXHJcbiAgICAgKiBAdGhyb3dzIHtSYW5nZUVycm9yfSBJZiBgb2Zmc2V0YCBpcyBvdXQgb2YgYm91bmRzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZEludDE2ID0gZnVuY3Rpb24ob2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMiA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzIrXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHZhbHVlID0gMDtcclxuICAgICAgICBpZiAodGhpcy5saXR0bGVFbmRpYW4pIHtcclxuICAgICAgICAgICAgdmFsdWUgID0gdGhpcy52aWV3W29mZnNldCAgXTtcclxuICAgICAgICAgICAgdmFsdWUgfD0gdGhpcy52aWV3W29mZnNldCsxXSA8PCA4O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHZhbHVlICA9IHRoaXMudmlld1tvZmZzZXQgIF0gPDwgODtcclxuICAgICAgICAgICAgdmFsdWUgfD0gdGhpcy52aWV3W29mZnNldCsxXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKCh2YWx1ZSAmIDB4ODAwMCkgPT09IDB4ODAwMCkgdmFsdWUgPSAtKDB4RkZGRiAtIHZhbHVlICsgMSk7IC8vIENhc3QgdG8gc2lnbmVkXHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB0aGlzLm9mZnNldCArPSAyO1xuICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYSAxNmJpdCBzaWduZWQgaW50ZWdlci4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlciNyZWFkSW50MTZ9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgYWR2YW5jZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGAyYCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn0gVmFsdWUgcmVhZFxyXG4gICAgICogQHRocm93cyB7VHlwZUVycm9yfSBJZiBgb2Zmc2V0YCBpcyBub3QgYSB2YWxpZCBudW1iZXJcclxuICAgICAqIEB0aHJvd3Mge1JhbmdlRXJyb3J9IElmIGBvZmZzZXRgIGlzIG91dCBvZiBib3VuZHNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkU2hvcnQgPSBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWRJbnQxNjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdyaXRlcyBhIDE2Yml0IHVuc2lnbmVkIGludGVnZXIuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgMmAgaWYgb21pdHRlZC5cclxuICAgICAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gSWYgYG9mZnNldGAgb3IgYHZhbHVlYCBpcyBub3QgYSB2YWxpZCBudW1iZXJcclxuICAgICAqIEB0aHJvd3Mge1JhbmdlRXJyb3J9IElmIGBvZmZzZXRgIGlzIG91dCBvZiBib3VuZHNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVVpbnQxNiA9IGZ1bmN0aW9uKHZhbHVlLCBvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIHZhbHVlOiBcIit2YWx1ZStcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgdmFsdWUgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInIHx8IG9mZnNldCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgb2Zmc2V0ID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCArIDAgPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIiswK1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIG9mZnNldCArPSAyO1xuICAgICAgICB2YXIgY2FwYWNpdHkzID0gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aDtcbiAgICAgICAgaWYgKG9mZnNldCA+IGNhcGFjaXR5MylcbiAgICAgICAgICAgIHRoaXMucmVzaXplKChjYXBhY2l0eTMgKj0gMikgPiBvZmZzZXQgPyBjYXBhY2l0eTMgOiBvZmZzZXQpO1xuICAgICAgICBvZmZzZXQgLT0gMjtcbiAgICAgICAgaWYgKHRoaXMubGl0dGxlRW5kaWFuKSB7XHJcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrMV0gPSAodmFsdWUgJiAweEZGMDApID4+PiA4O1xyXG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0ICBdID0gIHZhbHVlICYgMHgwMEZGO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXRdICAgPSAodmFsdWUgJiAweEZGMDApID4+PiA4O1xyXG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzFdID0gIHZhbHVlICYgMHgwMEZGO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAocmVsYXRpdmUpIHRoaXMub2Zmc2V0ICs9IDI7XG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdyaXRlcyBhIDE2Yml0IHVuc2lnbmVkIGludGVnZXIuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIEJ5dGVCdWZmZXIjd3JpdGVVaW50MTZ9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgMmAgaWYgb21pdHRlZC5cclxuICAgICAqIEB0aHJvd3Mge1R5cGVFcnJvcn0gSWYgYG9mZnNldGAgb3IgYHZhbHVlYCBpcyBub3QgYSB2YWxpZCBudW1iZXJcclxuICAgICAqIEB0aHJvd3Mge1JhbmdlRXJyb3J9IElmIGBvZmZzZXRgIGlzIG91dCBvZiBib3VuZHNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVVJbnQxNiA9IEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVVaW50MTY7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIDE2Yml0IHVuc2lnbmVkIGludGVnZXIuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgYWR2YW5jZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGAyYCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn0gVmFsdWUgcmVhZFxyXG4gICAgICogQHRocm93cyB7VHlwZUVycm9yfSBJZiBgb2Zmc2V0YCBpcyBub3QgYSB2YWxpZCBudW1iZXJcclxuICAgICAqIEB0aHJvd3Mge1JhbmdlRXJyb3J9IElmIGBvZmZzZXRgIGlzIG91dCBvZiBib3VuZHNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVWludDE2ID0gZnVuY3Rpb24ob2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMiA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzIrXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHZhbHVlID0gMDtcclxuICAgICAgICBpZiAodGhpcy5saXR0bGVFbmRpYW4pIHtcclxuICAgICAgICAgICAgdmFsdWUgID0gdGhpcy52aWV3W29mZnNldCAgXTtcclxuICAgICAgICAgICAgdmFsdWUgfD0gdGhpcy52aWV3W29mZnNldCsxXSA8PCA4O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHZhbHVlICA9IHRoaXMudmlld1tvZmZzZXQgIF0gPDwgODtcclxuICAgICAgICAgICAgdmFsdWUgfD0gdGhpcy52aWV3W29mZnNldCsxXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB0aGlzLm9mZnNldCArPSAyO1xuICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYSAxNmJpdCB1bnNpZ25lZCBpbnRlZ2VyLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBCeXRlQnVmZmVyI3JlYWRVaW50MTZ9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgYWR2YW5jZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGAyYCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn0gVmFsdWUgcmVhZFxyXG4gICAgICogQHRocm93cyB7VHlwZUVycm9yfSBJZiBgb2Zmc2V0YCBpcyBub3QgYSB2YWxpZCBudW1iZXJcclxuICAgICAqIEB0aHJvd3Mge1JhbmdlRXJyb3J9IElmIGBvZmZzZXRgIGlzIG91dCBvZiBib3VuZHNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVUludDE2ID0gQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVWludDE2O1xyXG5cclxuICAgIC8vIHR5cGVzL2ludHMvaW50MzJcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdyaXRlcyBhIDMyYml0IHNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA0YCBpZiBvbWl0dGVkLlxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlSW50MzIgPSBmdW5jdGlvbih2YWx1ZSwgb2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyB8fCB2YWx1ZSAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCB2YWx1ZTogXCIrdmFsdWUrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIHZhbHVlIHw9IDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzArXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgb2Zmc2V0ICs9IDQ7XG4gICAgICAgIHZhciBjYXBhY2l0eTQgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAob2Zmc2V0ID4gY2FwYWNpdHk0KVxuICAgICAgICAgICAgdGhpcy5yZXNpemUoKGNhcGFjaXR5NCAqPSAyKSA+IG9mZnNldCA/IGNhcGFjaXR5NCA6IG9mZnNldCk7XG4gICAgICAgIG9mZnNldCAtPSA0O1xuICAgICAgICBpZiAodGhpcy5saXR0bGVFbmRpYW4pIHtcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrM10gPSAodmFsdWUgPj4+IDI0KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzJdID0gKHZhbHVlID4+PiAxNikgJiAweEZGO1xuICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsxXSA9ICh2YWx1ZSA+Pj4gIDgpICYgMHhGRjtcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQgIF0gPSAgdmFsdWUgICAgICAgICAmIDB4RkY7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0ICBdID0gKHZhbHVlID4+PiAyNCkgJiAweEZGO1xuICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsxXSA9ICh2YWx1ZSA+Pj4gMTYpICYgMHhGRjtcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrMl0gPSAodmFsdWUgPj4+ICA4KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzNdID0gIHZhbHVlICAgICAgICAgJiAweEZGO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gNDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGEgMzJiaXQgc2lnbmVkIGludGVnZXIuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIEJ5dGVCdWZmZXIjd3JpdGVJbnQzMn0uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDRgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVJbnQgPSBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlSW50MzI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIDMyYml0IHNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDRgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZEludDMyID0gZnVuY3Rpb24ob2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgNCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzQrXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHZhbHVlID0gMDtcclxuICAgICAgICBpZiAodGhpcy5saXR0bGVFbmRpYW4pIHtcbiAgICAgICAgICAgIHZhbHVlICA9IHRoaXMudmlld1tvZmZzZXQrMl0gPDwgMTY7XG4gICAgICAgICAgICB2YWx1ZSB8PSB0aGlzLnZpZXdbb2Zmc2V0KzFdIDw8ICA4O1xuICAgICAgICAgICAgdmFsdWUgfD0gdGhpcy52aWV3W29mZnNldCAgXTtcbiAgICAgICAgICAgIHZhbHVlICs9IHRoaXMudmlld1tvZmZzZXQrM10gPDwgMjQgPj4+IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZSAgPSB0aGlzLnZpZXdbb2Zmc2V0KzFdIDw8IDE2O1xuICAgICAgICAgICAgdmFsdWUgfD0gdGhpcy52aWV3W29mZnNldCsyXSA8PCAgODtcbiAgICAgICAgICAgIHZhbHVlIHw9IHRoaXMudmlld1tvZmZzZXQrM107XG4gICAgICAgICAgICB2YWx1ZSArPSB0aGlzLnZpZXdbb2Zmc2V0ICBdIDw8IDI0ID4+PiAwO1xuICAgICAgICB9XG4gICAgICAgIHZhbHVlIHw9IDA7IC8vIENhc3QgdG8gc2lnbmVkXHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB0aGlzLm9mZnNldCArPSA0O1xuICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYSAzMmJpdCBzaWduZWQgaW50ZWdlci4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlciNyZWFkSW50MzJ9LlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGFkdmFuY2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgNGAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkSW50ID0gQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkSW50MzI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYSAzMmJpdCB1bnNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA0YCBpZiBvbWl0dGVkLlxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlVWludDMyID0gZnVuY3Rpb24odmFsdWUsIG9mZnNldCkge1xyXG4gICAgICAgIHZhciByZWxhdGl2ZSA9IHR5cGVvZiBvZmZzZXQgPT09ICd1bmRlZmluZWQnO1xuICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicgfHwgdmFsdWUgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgdmFsdWU6IFwiK3ZhbHVlK1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICB2YWx1ZSA+Pj49IDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzArXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgb2Zmc2V0ICs9IDQ7XG4gICAgICAgIHZhciBjYXBhY2l0eTUgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAob2Zmc2V0ID4gY2FwYWNpdHk1KVxuICAgICAgICAgICAgdGhpcy5yZXNpemUoKGNhcGFjaXR5NSAqPSAyKSA+IG9mZnNldCA/IGNhcGFjaXR5NSA6IG9mZnNldCk7XG4gICAgICAgIG9mZnNldCAtPSA0O1xuICAgICAgICBpZiAodGhpcy5saXR0bGVFbmRpYW4pIHtcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrM10gPSAodmFsdWUgPj4+IDI0KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzJdID0gKHZhbHVlID4+PiAxNikgJiAweEZGO1xuICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsxXSA9ICh2YWx1ZSA+Pj4gIDgpICYgMHhGRjtcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQgIF0gPSAgdmFsdWUgICAgICAgICAmIDB4RkY7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0ICBdID0gKHZhbHVlID4+PiAyNCkgJiAweEZGO1xuICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsxXSA9ICh2YWx1ZSA+Pj4gMTYpICYgMHhGRjtcbiAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrMl0gPSAodmFsdWUgPj4+ICA4KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzNdID0gIHZhbHVlICAgICAgICAgJiAweEZGO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gNDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGEgMzJiaXQgdW5zaWduZWQgaW50ZWdlci4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlciN3cml0ZVVpbnQzMn0uXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHdyaXRlIHRvLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgNGAgaWYgb21pdHRlZC5cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVVJbnQzMiA9IEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVVaW50MzI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIDMyYml0IHVuc2lnbmVkIGludGVnZXIuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgNGAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFZhbHVlIHJlYWRcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVWludDMyID0gZnVuY3Rpb24ob2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgNCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzQrXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHZhbHVlID0gMDtcclxuICAgICAgICBpZiAodGhpcy5saXR0bGVFbmRpYW4pIHtcbiAgICAgICAgICAgIHZhbHVlICA9IHRoaXMudmlld1tvZmZzZXQrMl0gPDwgMTY7XG4gICAgICAgICAgICB2YWx1ZSB8PSB0aGlzLnZpZXdbb2Zmc2V0KzFdIDw8ICA4O1xuICAgICAgICAgICAgdmFsdWUgfD0gdGhpcy52aWV3W29mZnNldCAgXTtcbiAgICAgICAgICAgIHZhbHVlICs9IHRoaXMudmlld1tvZmZzZXQrM10gPDwgMjQgPj4+IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZSAgPSB0aGlzLnZpZXdbb2Zmc2V0KzFdIDw8IDE2O1xuICAgICAgICAgICAgdmFsdWUgfD0gdGhpcy52aWV3W29mZnNldCsyXSA8PCAgODtcbiAgICAgICAgICAgIHZhbHVlIHw9IHRoaXMudmlld1tvZmZzZXQrM107XG4gICAgICAgICAgICB2YWx1ZSArPSB0aGlzLnZpZXdbb2Zmc2V0ICBdIDw8IDI0ID4+PiAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gNDtcbiAgICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlYWRzIGEgMzJiaXQgdW5zaWduZWQgaW50ZWdlci4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlciNyZWFkVWludDMyfS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDRgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBWYWx1ZSByZWFkXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZFVJbnQzMiA9IEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZFVpbnQzMjtcclxuXHJcbiAgICAvLyB0eXBlcy9pbnRzL2ludDY0XHJcblxyXG4gICAgaWYgKExvbmcpIHtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogV3JpdGVzIGEgNjRiaXQgc2lnbmVkIGludGVnZXIuXHJcbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHdyaXRlIHRvLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgOGAgaWYgb21pdHRlZC5cclxuICAgICAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAgICAgKiBAZXhwb3NlXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZUludDY0ID0gZnVuY3Rpb24odmFsdWUsIG9mZnNldCkge1xyXG4gICAgICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKVxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IExvbmcuZnJvbU51bWJlcih2YWx1ZSk7XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJylcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBMb25nLmZyb21TdHJpbmcodmFsdWUpO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKCEodmFsdWUgJiYgdmFsdWUgaW5zdGFuY2VvZiBMb25nKSlcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCB2YWx1ZTogXCIrdmFsdWUrXCIgKG5vdCBhbiBpbnRlZ2VyIG9yIExvbmcpXCIpO1xuICAgICAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ID4+Pj0gMDtcbiAgICAgICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzArXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJylcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IExvbmcuZnJvbU51bWJlcih2YWx1ZSk7XG4gICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKVxuICAgICAgICAgICAgICAgIHZhbHVlID0gTG9uZy5mcm9tU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgICAgIG9mZnNldCArPSA4O1xuICAgICAgICAgICAgdmFyIGNhcGFjaXR5NiA9IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICAgICAgICBpZiAob2Zmc2V0ID4gY2FwYWNpdHk2KVxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplKChjYXBhY2l0eTYgKj0gMikgPiBvZmZzZXQgPyBjYXBhY2l0eTYgOiBvZmZzZXQpO1xuICAgICAgICAgICAgb2Zmc2V0IC09IDg7XG4gICAgICAgICAgICB2YXIgbG8gPSB2YWx1ZS5sb3csXHJcbiAgICAgICAgICAgICAgICBoaSA9IHZhbHVlLmhpZ2g7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmxpdHRsZUVuZGlhbikge1xyXG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCszXSA9IChsbyA+Pj4gMjQpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzJdID0gKGxvID4+PiAxNikgJiAweEZGO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrMV0gPSAobG8gPj4+ICA4KSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCAgXSA9ICBsbyAgICAgICAgICYgMHhGRjtcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gNDtcclxuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrM10gPSAoaGkgPj4+IDI0KSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsyXSA9IChoaSA+Pj4gMTYpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzFdID0gKGhpID4+PiAgOCkgJiAweEZGO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQgIF0gPSAgaGkgICAgICAgICAmIDB4RkY7XG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCAgXSA9IChoaSA+Pj4gMjQpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzFdID0gKGhpID4+PiAxNikgJiAweEZGO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrMl0gPSAoaGkgPj4+ICA4KSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCszXSA9ICBoaSAgICAgICAgICYgMHhGRjtcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gNDtcclxuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQgIF0gPSAobG8gPj4+IDI0KSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsxXSA9IChsbyA+Pj4gMTYpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzJdID0gKGxvID4+PiAgOCkgJiAweEZGO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrM10gPSAgbG8gICAgICAgICAmIDB4RkY7XG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gODtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFdyaXRlcyBhIDY0Yml0IHNpZ25lZCBpbnRlZ2VyLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBCeXRlQnVmZmVyI3dyaXRlSW50NjR9LlxyXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfCFMb25nfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxyXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDhgIGlmIG9taXR0ZWQuXHJcbiAgICAgICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgICAgICogQGV4cG9zZVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVMb25nID0gQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZUludDY0O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBSZWFkcyBhIDY0Yml0IHNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byByZWFkIGZyb20uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA4YCBpZiBvbWl0dGVkLlxyXG4gICAgICAgICAqIEByZXR1cm5zIHshTG9uZ31cclxuICAgICAgICAgKiBAZXhwb3NlXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkSW50NjQgPSBmdW5jdGlvbihvZmZzZXQpIHtcclxuICAgICAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgOCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIis4K1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdmFyIGxvID0gMCxcclxuICAgICAgICAgICAgICAgIGhpID0gMDtcclxuICAgICAgICAgICAgaWYgKHRoaXMubGl0dGxlRW5kaWFuKSB7XHJcbiAgICAgICAgICAgICAgICBsbyAgPSB0aGlzLnZpZXdbb2Zmc2V0KzJdIDw8IDE2O1xuICAgICAgICAgICAgICAgIGxvIHw9IHRoaXMudmlld1tvZmZzZXQrMV0gPDwgIDg7XG4gICAgICAgICAgICAgICAgbG8gfD0gdGhpcy52aWV3W29mZnNldCAgXTtcbiAgICAgICAgICAgICAgICBsbyArPSB0aGlzLnZpZXdbb2Zmc2V0KzNdIDw8IDI0ID4+PiAwO1xuICAgICAgICAgICAgICAgIG9mZnNldCArPSA0O1xyXG4gICAgICAgICAgICAgICAgaGkgID0gdGhpcy52aWV3W29mZnNldCsyXSA8PCAxNjtcbiAgICAgICAgICAgICAgICBoaSB8PSB0aGlzLnZpZXdbb2Zmc2V0KzFdIDw8ICA4O1xuICAgICAgICAgICAgICAgIGhpIHw9IHRoaXMudmlld1tvZmZzZXQgIF07XG4gICAgICAgICAgICAgICAgaGkgKz0gdGhpcy52aWV3W29mZnNldCszXSA8PCAyNCA+Pj4gMDtcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBoaSAgPSB0aGlzLnZpZXdbb2Zmc2V0KzFdIDw8IDE2O1xuICAgICAgICAgICAgICAgIGhpIHw9IHRoaXMudmlld1tvZmZzZXQrMl0gPDwgIDg7XG4gICAgICAgICAgICAgICAgaGkgfD0gdGhpcy52aWV3W29mZnNldCszXTtcbiAgICAgICAgICAgICAgICBoaSArPSB0aGlzLnZpZXdbb2Zmc2V0ICBdIDw8IDI0ID4+PiAwO1xuICAgICAgICAgICAgICAgIG9mZnNldCArPSA0O1xyXG4gICAgICAgICAgICAgICAgbG8gID0gdGhpcy52aWV3W29mZnNldCsxXSA8PCAxNjtcbiAgICAgICAgICAgICAgICBsbyB8PSB0aGlzLnZpZXdbb2Zmc2V0KzJdIDw8ICA4O1xuICAgICAgICAgICAgICAgIGxvIHw9IHRoaXMudmlld1tvZmZzZXQrM107XG4gICAgICAgICAgICAgICAgbG8gKz0gdGhpcy52aWV3W29mZnNldCAgXSA8PCAyNCA+Pj4gMDtcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgdmFyIHZhbHVlID0gbmV3IExvbmcobG8sIGhpLCBmYWxzZSk7XHJcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gODtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBSZWFkcyBhIDY0Yml0IHNpZ25lZCBpbnRlZ2VyLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBCeXRlQnVmZmVyI3JlYWRJbnQ2NH0uXHJcbiAgICAgICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDhgIGlmIG9taXR0ZWQuXHJcbiAgICAgICAgICogQHJldHVybnMgeyFMb25nfVxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKi9cclxuICAgICAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWRMb25nID0gQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkSW50NjQ7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFdyaXRlcyBhIDY0Yml0IHVuc2lnbmVkIGludGVnZXIuXHJcbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHdyaXRlIHRvLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgOGAgaWYgb21pdHRlZC5cclxuICAgICAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAgICAgKiBAZXhwb3NlXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVVpbnQ2NCA9IGZ1bmN0aW9uKHZhbHVlLCBvZmZzZXQpIHtcclxuICAgICAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJylcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBMb25nLmZyb21OdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gTG9uZy5mcm9tU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICghKHZhbHVlICYmIHZhbHVlIGluc3RhbmNlb2YgTG9uZykpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgdmFsdWU6IFwiK3ZhbHVlK1wiIChub3QgYW4gaW50ZWdlciBvciBMb25nKVwiKTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIiswK1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBMb25nLmZyb21OdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJylcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IExvbmcuZnJvbVN0cmluZyh2YWx1ZSk7XG4gICAgICAgICAgICBvZmZzZXQgKz0gODtcbiAgICAgICAgICAgIHZhciBjYXBhY2l0eTcgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA+IGNhcGFjaXR5NylcbiAgICAgICAgICAgICAgICB0aGlzLnJlc2l6ZSgoY2FwYWNpdHk3ICo9IDIpID4gb2Zmc2V0ID8gY2FwYWNpdHk3IDogb2Zmc2V0KTtcbiAgICAgICAgICAgIG9mZnNldCAtPSA4O1xuICAgICAgICAgICAgdmFyIGxvID0gdmFsdWUubG93LFxyXG4gICAgICAgICAgICAgICAgaGkgPSB2YWx1ZS5oaWdoO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5saXR0bGVFbmRpYW4pIHtcclxuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrM10gPSAobG8gPj4+IDI0KSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsyXSA9IChsbyA+Pj4gMTYpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzFdID0gKGxvID4+PiAgOCkgJiAweEZGO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQgIF0gPSAgbG8gICAgICAgICAmIDB4RkY7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ICs9IDQ7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzNdID0gKGhpID4+PiAyNCkgJiAweEZGO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrMl0gPSAoaGkgPj4+IDE2KSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsxXSA9IChoaSA+Pj4gIDgpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0ICBdID0gIGhpICAgICAgICAgJiAweEZGO1xuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQgIF0gPSAoaGkgPj4+IDI0KSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsxXSA9IChoaSA+Pj4gMTYpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzJdID0gKGhpID4+PiAgOCkgJiAweEZGO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrM10gPSAgaGkgICAgICAgICAmIDB4RkY7XG4gICAgICAgICAgICAgICAgb2Zmc2V0ICs9IDQ7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0ICBdID0gKGxvID4+PiAyNCkgJiAweEZGO1xuICAgICAgICAgICAgICAgIHRoaXMudmlld1tvZmZzZXQrMV0gPSAobG8gPj4+IDE2KSAmIDB4RkY7XG4gICAgICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsyXSA9IChsbyA+Pj4gIDgpICYgMHhGRjtcbiAgICAgICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzNdID0gIGxvICAgICAgICAgJiAweEZGO1xuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAocmVsYXRpdmUpIHRoaXMub2Zmc2V0ICs9IDg7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBXcml0ZXMgYSA2NGJpdCB1bnNpZ25lZCBpbnRlZ2VyLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBCeXRlQnVmZmVyI3dyaXRlVWludDY0fS5cclxuICAgICAgICAgKiBAZnVuY3Rpb25cclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA4YCBpZiBvbWl0dGVkLlxyXG4gICAgICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKi9cclxuICAgICAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlVUludDY0ID0gQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVVpbnQ2NDtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogUmVhZHMgYSA2NGJpdCB1bnNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byByZWFkIGZyb20uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA4YCBpZiBvbWl0dGVkLlxyXG4gICAgICAgICAqIEByZXR1cm5zIHshTG9uZ31cclxuICAgICAgICAgKiBAZXhwb3NlXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVWludDY0ID0gZnVuY3Rpb24ob2Zmc2V0KSB7XHJcbiAgICAgICAgICAgIHZhciByZWxhdGl2ZSA9IHR5cGVvZiBvZmZzZXQgPT09ICd1bmRlZmluZWQnO1xuICAgICAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInIHx8IG9mZnNldCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCArIDggPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrOCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHZhciBsbyA9IDAsXHJcbiAgICAgICAgICAgICAgICBoaSA9IDA7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmxpdHRsZUVuZGlhbikge1xyXG4gICAgICAgICAgICAgICAgbG8gID0gdGhpcy52aWV3W29mZnNldCsyXSA8PCAxNjtcbiAgICAgICAgICAgICAgICBsbyB8PSB0aGlzLnZpZXdbb2Zmc2V0KzFdIDw8ICA4O1xuICAgICAgICAgICAgICAgIGxvIHw9IHRoaXMudmlld1tvZmZzZXQgIF07XG4gICAgICAgICAgICAgICAgbG8gKz0gdGhpcy52aWV3W29mZnNldCszXSA8PCAyNCA+Pj4gMDtcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gNDtcclxuICAgICAgICAgICAgICAgIGhpICA9IHRoaXMudmlld1tvZmZzZXQrMl0gPDwgMTY7XG4gICAgICAgICAgICAgICAgaGkgfD0gdGhpcy52aWV3W29mZnNldCsxXSA8PCAgODtcbiAgICAgICAgICAgICAgICBoaSB8PSB0aGlzLnZpZXdbb2Zmc2V0ICBdO1xuICAgICAgICAgICAgICAgIGhpICs9IHRoaXMudmlld1tvZmZzZXQrM10gPDwgMjQgPj4+IDA7XG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgaGkgID0gdGhpcy52aWV3W29mZnNldCsxXSA8PCAxNjtcbiAgICAgICAgICAgICAgICBoaSB8PSB0aGlzLnZpZXdbb2Zmc2V0KzJdIDw8ICA4O1xuICAgICAgICAgICAgICAgIGhpIHw9IHRoaXMudmlld1tvZmZzZXQrM107XG4gICAgICAgICAgICAgICAgaGkgKz0gdGhpcy52aWV3W29mZnNldCAgXSA8PCAyNCA+Pj4gMDtcbiAgICAgICAgICAgICAgICBvZmZzZXQgKz0gNDtcclxuICAgICAgICAgICAgICAgIGxvICA9IHRoaXMudmlld1tvZmZzZXQrMV0gPDwgMTY7XG4gICAgICAgICAgICAgICAgbG8gfD0gdGhpcy52aWV3W29mZnNldCsyXSA8PCAgODtcbiAgICAgICAgICAgICAgICBsbyB8PSB0aGlzLnZpZXdbb2Zmc2V0KzNdO1xuICAgICAgICAgICAgICAgIGxvICs9IHRoaXMudmlld1tvZmZzZXQgIF0gPDwgMjQgPj4+IDA7XG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHZhciB2YWx1ZSA9IG5ldyBMb25nKGxvLCBoaSwgdHJ1ZSk7XHJcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gODtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBSZWFkcyBhIDY0Yml0IHVuc2lnbmVkIGludGVnZXIuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIEJ5dGVCdWZmZXIjcmVhZFVpbnQ2NH0uXHJcbiAgICAgICAgICogQGZ1bmN0aW9uXHJcbiAgICAgICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDhgIGlmIG9taXR0ZWQuXHJcbiAgICAgICAgICogQHJldHVybnMgeyFMb25nfVxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKi9cclxuICAgICAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWRVSW50NjQgPSBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWRVaW50NjQ7XHJcblxyXG4gICAgfSAvLyBMb25nXHJcblxyXG5cclxuICAgIC8vIHR5cGVzL2Zsb2F0cy9mbG9hdDMyXHJcblxyXG4gICAgLypcclxuICAgICBpZWVlNzU0IC0gaHR0cHM6Ly9naXRodWIuY29tL2Zlcm9zcy9pZWVlNzU0XHJcblxyXG4gICAgIFRoZSBNSVQgTGljZW5zZSAoTUlUKVxyXG5cclxuICAgICBDb3B5cmlnaHQgKGMpIEZlcm9zcyBBYm91a2hhZGlqZWhcclxuXHJcbiAgICAgUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxyXG4gICAgIG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWxcclxuICAgICBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzXHJcbiAgICAgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxyXG4gICAgIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpc1xyXG4gICAgIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nIGNvbmRpdGlvbnM6XHJcblxyXG4gICAgIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluXHJcbiAgICAgYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXHJcblxyXG4gICAgIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1JcclxuICAgICBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcclxuICAgICBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEVcclxuICAgICBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSXHJcbiAgICAgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcclxuICAgICBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SIE9USEVSIERFQUxJTkdTIElOXHJcbiAgICAgVEhFIFNPRlRXQVJFLlxyXG4gICAgKi9cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlYWRzIGFuIElFRUU3NTQgZmxvYXQgZnJvbSBhIGJ5dGUgYXJyYXkuXHJcbiAgICAgKiBAcGFyYW0geyFBcnJheX0gYnVmZmVyXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0XHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzTEVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtTGVuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbkJ5dGVzXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIGZ1bmN0aW9uIGllZWU3NTRfcmVhZChidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XHJcbiAgICAgICAgdmFyIGUsIG0sXHJcbiAgICAgICAgICAgIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDEsXHJcbiAgICAgICAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXHJcbiAgICAgICAgICAgIGVCaWFzID0gZU1heCA+PiAxLFxyXG4gICAgICAgICAgICBuQml0cyA9IC03LFxyXG4gICAgICAgICAgICBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDAsXHJcbiAgICAgICAgICAgIGQgPSBpc0xFID8gLTEgOiAxLFxyXG4gICAgICAgICAgICBzID0gYnVmZmVyW29mZnNldCArIGldO1xyXG5cclxuICAgICAgICBpICs9IGQ7XHJcblxyXG4gICAgICAgIGUgPSBzICYgKCgxIDw8ICgtbkJpdHMpKSAtIDEpO1xyXG4gICAgICAgIHMgPj49ICgtbkJpdHMpO1xyXG4gICAgICAgIG5CaXRzICs9IGVMZW47XHJcbiAgICAgICAgZm9yICg7IG5CaXRzID4gMDsgZSA9IGUgKiAyNTYgKyBidWZmZXJbb2Zmc2V0ICsgaV0sIGkgKz0gZCwgbkJpdHMgLT0gOCkge31cclxuXHJcbiAgICAgICAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSk7XHJcbiAgICAgICAgZSA+Pj0gKC1uQml0cyk7XHJcbiAgICAgICAgbkJpdHMgKz0gbUxlbjtcclxuICAgICAgICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gbSAqIDI1NiArIGJ1ZmZlcltvZmZzZXQgKyBpXSwgaSArPSBkLCBuQml0cyAtPSA4KSB7fVxyXG5cclxuICAgICAgICBpZiAoZSA9PT0gMCkge1xyXG4gICAgICAgICAgICBlID0gMSAtIGVCaWFzO1xyXG4gICAgICAgIH0gZWxzZSBpZiAoZSA9PT0gZU1heCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbSA/IE5hTiA6ICgocyA/IC0xIDogMSkgKiBJbmZpbml0eSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbSA9IG0gKyBNYXRoLnBvdygyLCBtTGVuKTtcclxuICAgICAgICAgICAgZSA9IGUgLSBlQmlhcztcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIChzID8gLTEgOiAxKSAqIG0gKiBNYXRoLnBvdygyLCBlIC0gbUxlbik7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYW4gSUVFRTc1NCBmbG9hdCB0byBhIGJ5dGUgYXJyYXkuXHJcbiAgICAgKiBAcGFyYW0geyFBcnJheX0gYnVmZmVyXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBvZmZzZXRcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNMRVxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1MZW5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuQnl0ZXNcclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICBmdW5jdGlvbiBpZWVlNzU0X3dyaXRlKGJ1ZmZlciwgdmFsdWUsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XHJcbiAgICAgICAgdmFyIGUsIG0sIGMsXHJcbiAgICAgICAgICAgIGVMZW4gPSBuQnl0ZXMgKiA4IC0gbUxlbiAtIDEsXHJcbiAgICAgICAgICAgIGVNYXggPSAoMSA8PCBlTGVuKSAtIDEsXHJcbiAgICAgICAgICAgIGVCaWFzID0gZU1heCA+PiAxLFxyXG4gICAgICAgICAgICBydCA9IChtTGVuID09PSAyMyA/IE1hdGgucG93KDIsIC0yNCkgLSBNYXRoLnBvdygyLCAtNzcpIDogMCksXHJcbiAgICAgICAgICAgIGkgPSBpc0xFID8gMCA6IChuQnl0ZXMgLSAxKSxcclxuICAgICAgICAgICAgZCA9IGlzTEUgPyAxIDogLTEsXHJcbiAgICAgICAgICAgIHMgPSB2YWx1ZSA8IDAgfHwgKHZhbHVlID09PSAwICYmIDEgLyB2YWx1ZSA8IDApID8gMSA6IDA7XHJcblxyXG4gICAgICAgIHZhbHVlID0gTWF0aC5hYnModmFsdWUpO1xyXG5cclxuICAgICAgICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xyXG4gICAgICAgICAgICBtID0gaXNOYU4odmFsdWUpID8gMSA6IDA7XHJcbiAgICAgICAgICAgIGUgPSBlTWF4O1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGUgPSBNYXRoLmZsb29yKE1hdGgubG9nKHZhbHVlKSAvIE1hdGguTE4yKTtcclxuICAgICAgICAgICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xyXG4gICAgICAgICAgICAgICAgZS0tO1xyXG4gICAgICAgICAgICAgICAgYyAqPSAyO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChlICsgZUJpYXMgPj0gMSkge1xyXG4gICAgICAgICAgICAgICAgdmFsdWUgKz0gcnQgLyBjO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xyXG4gICAgICAgICAgICAgICAgZSsrO1xyXG4gICAgICAgICAgICAgICAgYyAvPSAyO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcclxuICAgICAgICAgICAgICAgIG0gPSAwO1xyXG4gICAgICAgICAgICAgICAgZSA9IGVNYXg7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZSArIGVCaWFzID49IDEpIHtcclxuICAgICAgICAgICAgICAgIG0gPSAodmFsdWUgKiBjIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKTtcclxuICAgICAgICAgICAgICAgIGUgPSBlICsgZUJpYXM7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBtID0gdmFsdWUgKiBNYXRoLnBvdygyLCBlQmlhcyAtIDEpICogTWF0aC5wb3coMiwgbUxlbik7XHJcbiAgICAgICAgICAgICAgICBlID0gMDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yICg7IG1MZW4gPj0gODsgYnVmZmVyW29mZnNldCArIGldID0gbSAmIDB4ZmYsIGkgKz0gZCwgbSAvPSAyNTYsIG1MZW4gLT0gOCkge31cclxuXHJcbiAgICAgICAgZSA9IChlIDw8IG1MZW4pIHwgbTtcclxuICAgICAgICBlTGVuICs9IG1MZW47XHJcbiAgICAgICAgZm9yICg7IGVMZW4gPiAwOyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBlICYgMHhmZiwgaSArPSBkLCBlIC89IDI1NiwgZUxlbiAtPSA4KSB7fVxyXG5cclxuICAgICAgICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjg7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYSAzMmJpdCBmbG9hdC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHdyaXRlIHRvLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSBgNGAgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlRmxvYXQzMiA9IGZ1bmN0aW9uKHZhbHVlLCBvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCB2YWx1ZTogXCIrdmFsdWUrXCIgKG5vdCBhIG51bWJlcilcIik7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICBvZmZzZXQgKz0gNDtcbiAgICAgICAgdmFyIGNhcGFjaXR5OCA9IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICAgIGlmIChvZmZzZXQgPiBjYXBhY2l0eTgpXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZSgoY2FwYWNpdHk4ICo9IDIpID4gb2Zmc2V0ID8gY2FwYWNpdHk4IDogb2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0IC09IDQ7XG4gICAgICAgIGllZWU3NTRfd3JpdGUodGhpcy52aWV3LCB2YWx1ZSwgb2Zmc2V0LCB0aGlzLmxpdHRsZUVuZGlhbiwgMjMsIDQpO1xyXG4gICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgKz0gNDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGEgMzJiaXQgZmxvYXQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIEJ5dGVCdWZmZXIjd3JpdGVGbG9hdDMyfS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA0YCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVGbG9hdCA9IEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVGbG9hdDMyO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYSAzMmJpdCBmbG9hdC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byByZWFkIGZyb20uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA0YCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn1cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkRmxvYXQzMiA9IGZ1bmN0aW9uKG9mZnNldCkge1xyXG4gICAgICAgIHZhciByZWxhdGl2ZSA9IHR5cGVvZiBvZmZzZXQgPT09ICd1bmRlZmluZWQnO1xuICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInIHx8IG9mZnNldCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgb2Zmc2V0ID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCArIDQgPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIis0K1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciB2YWx1ZSA9IGllZWU3NTRfcmVhZCh0aGlzLnZpZXcsIG9mZnNldCwgdGhpcy5saXR0bGVFbmRpYW4sIDIzLCA0KTtcclxuICAgICAgICBpZiAocmVsYXRpdmUpIHRoaXMub2Zmc2V0ICs9IDQ7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIDMyYml0IGZsb2F0LiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBCeXRlQnVmZmVyI3JlYWRGbG9hdDMyfS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDRgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWRGbG9hdCA9IEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZEZsb2F0MzI7XHJcblxyXG4gICAgLy8gdHlwZXMvZmxvYXRzL2Zsb2F0NjRcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdyaXRlcyBhIDY0Yml0IGZsb2F0LlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA4YCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVGbG9hdDY0ID0gZnVuY3Rpb24odmFsdWUsIG9mZnNldCkge1xyXG4gICAgICAgIHZhciByZWxhdGl2ZSA9IHR5cGVvZiBvZmZzZXQgPT09ICd1bmRlZmluZWQnO1xuICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ251bWJlcicpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIHZhbHVlOiBcIit2YWx1ZStcIiAobm90IGEgbnVtYmVyKVwiKTtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInIHx8IG9mZnNldCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgb2Zmc2V0ID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCArIDAgPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIiswK1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIG9mZnNldCArPSA4O1xuICAgICAgICB2YXIgY2FwYWNpdHk5ID0gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aDtcbiAgICAgICAgaWYgKG9mZnNldCA+IGNhcGFjaXR5OSlcbiAgICAgICAgICAgIHRoaXMucmVzaXplKChjYXBhY2l0eTkgKj0gMikgPiBvZmZzZXQgPyBjYXBhY2l0eTkgOiBvZmZzZXQpO1xuICAgICAgICBvZmZzZXQgLT0gODtcbiAgICAgICAgaWVlZTc1NF93cml0ZSh0aGlzLnZpZXcsIHZhbHVlLCBvZmZzZXQsIHRoaXMubGl0dGxlRW5kaWFuLCA1MiwgOCk7XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB0aGlzLm9mZnNldCArPSA4O1xuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYSA2NGJpdCBmbG9hdC4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlciN3cml0ZUZsb2F0NjR9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDhgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZURvdWJsZSA9IEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVGbG9hdDY0O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYSA2NGJpdCBmbG9hdC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byByZWFkIGZyb20uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IGA4YCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn1cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkRmxvYXQ2NCA9IGZ1bmN0aW9uKG9mZnNldCkge1xyXG4gICAgICAgIHZhciByZWxhdGl2ZSA9IHR5cGVvZiBvZmZzZXQgPT09ICd1bmRlZmluZWQnO1xuICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInIHx8IG9mZnNldCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgb2Zmc2V0ID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCArIDggPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIis4K1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciB2YWx1ZSA9IGllZWU3NTRfcmVhZCh0aGlzLnZpZXcsIG9mZnNldCwgdGhpcy5saXR0bGVFbmRpYW4sIDUyLCA4KTtcclxuICAgICAgICBpZiAocmVsYXRpdmUpIHRoaXMub2Zmc2V0ICs9IDg7XG4gICAgICAgIHJldHVybiB2YWx1ZTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIDY0Yml0IGZsb2F0LiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBCeXRlQnVmZmVyI3JlYWRGbG9hdDY0fS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgYDhgIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWREb3VibGUgPSBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWRGbG9hdDY0O1xyXG5cclxuXHJcbiAgICAvLyB0eXBlcy92YXJpbnRzL3ZhcmludDMyXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNYXhpbXVtIG51bWJlciBvZiBieXRlcyByZXF1aXJlZCB0byBzdG9yZSBhIDMyYml0IGJhc2UgMTI4IHZhcmlhYmxlLWxlbmd0aCBpbnRlZ2VyLlxyXG4gICAgICogQHR5cGUge251bWJlcn1cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLk1BWF9WQVJJTlQzMl9CWVRFUyA9IDU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxjdWxhdGVzIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGJ5dGVzIHJlcXVpcmVkIHRvIHN0b3JlIGEgMzJiaXQgYmFzZSAxMjggdmFyaWFibGUtbGVuZ3RoIGludGVnZXIuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gZW5jb2RlXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1iZXIgb2YgYnl0ZXMgcmVxdWlyZWQuIENhcHBlZCB0byB7QGxpbmsgQnl0ZUJ1ZmZlci5NQVhfVkFSSU5UMzJfQllURVN9XHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuY2FsY3VsYXRlVmFyaW50MzIgPSBmdW5jdGlvbih2YWx1ZSkge1xyXG4gICAgICAgIC8vIHJlZjogc3JjL2dvb2dsZS9wcm90b2J1Zi9pby9jb2RlZF9zdHJlYW0uY2NcclxuICAgICAgICB2YWx1ZSA9IHZhbHVlID4+PiAwO1xyXG4gICAgICAgICAgICAgaWYgKHZhbHVlIDwgMSA8PCA3ICkgcmV0dXJuIDE7XHJcbiAgICAgICAgZWxzZSBpZiAodmFsdWUgPCAxIDw8IDE0KSByZXR1cm4gMjtcclxuICAgICAgICBlbHNlIGlmICh2YWx1ZSA8IDEgPDwgMjEpIHJldHVybiAzO1xyXG4gICAgICAgIGVsc2UgaWYgKHZhbHVlIDwgMSA8PCAyOCkgcmV0dXJuIDQ7XHJcbiAgICAgICAgZWxzZSAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gNTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBaaWd6YWcgZW5jb2RlcyBhIHNpZ25lZCAzMmJpdCBpbnRlZ2VyIHNvIHRoYXQgaXQgY2FuIGJlIGVmZmVjdGl2ZWx5IHVzZWQgd2l0aCB2YXJpbnQgZW5jb2RpbmcuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbiBTaWduZWQgMzJiaXQgaW50ZWdlclxyXG4gICAgICogQHJldHVybnMge251bWJlcn0gVW5zaWduZWQgemlnemFnIGVuY29kZWQgMzJiaXQgaW50ZWdlclxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLnppZ1phZ0VuY29kZTMyID0gZnVuY3Rpb24obikge1xyXG4gICAgICAgIHJldHVybiAoKChuIHw9IDApIDw8IDEpIF4gKG4gPj4gMzEpKSA+Pj4gMDsgLy8gcmVmOiBzcmMvZ29vZ2xlL3Byb3RvYnVmL3dpcmVfZm9ybWF0X2xpdGUuaFxyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlY29kZXMgYSB6aWd6YWcgZW5jb2RlZCBzaWduZWQgMzJiaXQgaW50ZWdlci5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBuIFVuc2lnbmVkIHppZ3phZyBlbmNvZGVkIDMyYml0IGludGVnZXJcclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IFNpZ25lZCAzMmJpdCBpbnRlZ2VyXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuemlnWmFnRGVjb2RlMzIgPSBmdW5jdGlvbihuKSB7XHJcbiAgICAgICAgcmV0dXJuICgobiA+Pj4gMSkgXiAtKG4gJiAxKSkgfCAwOyAvLyAvLyByZWY6IHNyYy9nb29nbGUvcHJvdG9idWYvd2lyZV9mb3JtYXRfbGl0ZS5oXHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGEgMzJiaXQgYmFzZSAxMjggdmFyaWFibGUtbGVuZ3RoIGludGVnZXIuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgdGhlIG51bWJlciBvZiBieXRlc1xyXG4gICAgICogIHdyaXR0ZW4gaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcnxudW1iZXJ9IHRoaXMgaWYgYG9mZnNldGAgaXMgb21pdHRlZCwgZWxzZSB0aGUgYWN0dWFsIG51bWJlciBvZiBieXRlcyB3cml0dGVuXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVWYXJpbnQzMiA9IGZ1bmN0aW9uKHZhbHVlLCBvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgIT09ICdudW1iZXInIHx8IHZhbHVlICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIHZhbHVlOiBcIit2YWx1ZStcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgdmFsdWUgfD0gMDtcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc2l6ZSA9IEJ5dGVCdWZmZXIuY2FsY3VsYXRlVmFyaW50MzIodmFsdWUpLFxyXG4gICAgICAgICAgICBiO1xyXG4gICAgICAgIG9mZnNldCArPSBzaXplO1xuICAgICAgICB2YXIgY2FwYWNpdHkxMCA9IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICAgIGlmIChvZmZzZXQgPiBjYXBhY2l0eTEwKVxuICAgICAgICAgICAgdGhpcy5yZXNpemUoKGNhcGFjaXR5MTAgKj0gMikgPiBvZmZzZXQgPyBjYXBhY2l0eTEwIDogb2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0IC09IHNpemU7XG4gICAgICAgIHZhbHVlID4+Pj0gMDtcclxuICAgICAgICB3aGlsZSAodmFsdWUgPj0gMHg4MCkge1xyXG4gICAgICAgICAgICBiID0gKHZhbHVlICYgMHg3ZikgfCAweDgwO1xyXG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KytdID0gYjtcclxuICAgICAgICAgICAgdmFsdWUgPj4+PSA3O1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KytdID0gdmFsdWU7XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB7XHJcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0ID0gb2Zmc2V0O1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHNpemU7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGEgemlnLXphZyBlbmNvZGVkIChzaWduZWQpIDMyYml0IGJhc2UgMTI4IHZhcmlhYmxlLWxlbmd0aCBpbnRlZ2VyLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFZhbHVlIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IHRoZSBudW1iZXIgb2YgYnl0ZXNcclxuICAgICAqICB3cml0dGVuIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ8bnVtYmVyfSB0aGlzIGlmIGBvZmZzZXRgIGlzIG9taXR0ZWQsIGVsc2UgdGhlIGFjdHVhbCBudW1iZXIgb2YgYnl0ZXMgd3JpdHRlblxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlVmFyaW50MzJaaWdaYWcgPSBmdW5jdGlvbih2YWx1ZSwgb2Zmc2V0KSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMud3JpdGVWYXJpbnQzMihCeXRlQnVmZmVyLnppZ1phZ0VuY29kZTMyKHZhbHVlKSwgb2Zmc2V0KTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIDMyYml0IGJhc2UgMTI4IHZhcmlhYmxlLWxlbmd0aCBpbnRlZ2VyLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgdGhlIG51bWJlciBvZiBieXRlc1xyXG4gICAgICogIHdyaXR0ZW4gaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ8IXt2YWx1ZTogbnVtYmVyLCBsZW5ndGg6IG51bWJlcn19IFRoZSB2YWx1ZSByZWFkIGlmIG9mZnNldCBpcyBvbWl0dGVkLCBlbHNlIHRoZSB2YWx1ZSByZWFkXHJcbiAgICAgKiAgYW5kIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGJ5dGVzIHJlYWQuXHJcbiAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgaXQncyBub3QgYSB2YWxpZCB2YXJpbnQuIEhhcyBhIHByb3BlcnR5IGB0cnVuY2F0ZWQgPSB0cnVlYCBpZiB0aGVyZSBpcyBub3QgZW5vdWdoIGRhdGEgYXZhaWxhYmxlXHJcbiAgICAgKiAgdG8gZnVsbHkgZGVjb2RlIHRoZSB2YXJpbnQuXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZFZhcmludDMyID0gZnVuY3Rpb24ob2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMSA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzErXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGMgPSAwLFxyXG4gICAgICAgICAgICB2YWx1ZSA9IDAgPj4+IDAsXHJcbiAgICAgICAgICAgIGI7XHJcbiAgICAgICAgZG8ge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQgJiYgb2Zmc2V0ID4gdGhpcy5saW1pdCkge1xyXG4gICAgICAgICAgICAgICAgdmFyIGVyciA9IEVycm9yKFwiVHJ1bmNhdGVkXCIpO1xyXG4gICAgICAgICAgICAgICAgZXJyWyd0cnVuY2F0ZWQnXSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgYiA9IHRoaXMudmlld1tvZmZzZXQrK107XHJcbiAgICAgICAgICAgIGlmIChjIDwgNSlcclxuICAgICAgICAgICAgICAgIHZhbHVlIHw9IChiICYgMHg3ZikgPDwgKDcqYyk7XHJcbiAgICAgICAgICAgICsrYztcclxuICAgICAgICB9IHdoaWxlICgoYiAmIDB4ODApICE9PSAwKTtcclxuICAgICAgICB2YWx1ZSB8PSAwO1xyXG4gICAgICAgIGlmIChyZWxhdGl2ZSkge1xyXG4gICAgICAgICAgICB0aGlzLm9mZnNldCA9IG9mZnNldDtcclxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBcInZhbHVlXCI6IHZhbHVlLFxyXG4gICAgICAgICAgICBcImxlbmd0aFwiOiBjXHJcbiAgICAgICAgfTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIHppZy16YWcgZW5jb2RlZCAoc2lnbmVkKSAzMmJpdCBiYXNlIDEyOCB2YXJpYWJsZS1sZW5ndGggaW50ZWdlci5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byByZWFkIGZyb20uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IHRoZSBudW1iZXIgb2YgYnl0ZXNcclxuICAgICAqICB3cml0dGVuIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfCF7dmFsdWU6IG51bWJlciwgbGVuZ3RoOiBudW1iZXJ9fSBUaGUgdmFsdWUgcmVhZCBpZiBvZmZzZXQgaXMgb21pdHRlZCwgZWxzZSB0aGUgdmFsdWUgcmVhZFxyXG4gICAgICogIGFuZCB0aGUgYWN0dWFsIG51bWJlciBvZiBieXRlcyByZWFkLlxyXG4gICAgICogQHRocm93cyB7RXJyb3J9IElmIGl0J3Mgbm90IGEgdmFsaWQgdmFyaW50XHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZFZhcmludDMyWmlnWmFnID0gZnVuY3Rpb24ob2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHZhbCA9IHRoaXMucmVhZFZhcmludDMyKG9mZnNldCk7XHJcbiAgICAgICAgaWYgKHR5cGVvZiB2YWwgPT09ICdvYmplY3QnKVxyXG4gICAgICAgICAgICB2YWxbXCJ2YWx1ZVwiXSA9IEJ5dGVCdWZmZXIuemlnWmFnRGVjb2RlMzIodmFsW1widmFsdWVcIl0pO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgdmFsID0gQnl0ZUJ1ZmZlci56aWdaYWdEZWNvZGUzMih2YWwpO1xyXG4gICAgICAgIHJldHVybiB2YWw7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIHR5cGVzL3ZhcmludHMvdmFyaW50NjRcclxuXHJcbiAgICBpZiAoTG9uZykge1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBNYXhpbXVtIG51bWJlciBvZiBieXRlcyByZXF1aXJlZCB0byBzdG9yZSBhIDY0Yml0IGJhc2UgMTI4IHZhcmlhYmxlLWxlbmd0aCBpbnRlZ2VyLlxyXG4gICAgICAgICAqIEB0eXBlIHtudW1iZXJ9XHJcbiAgICAgICAgICogQGNvbnN0XHJcbiAgICAgICAgICogQGV4cG9zZVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIEJ5dGVCdWZmZXIuTUFYX1ZBUklOVDY0X0JZVEVTID0gMTA7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGFjdHVhbCBudW1iZXIgb2YgYnl0ZXMgcmVxdWlyZWQgdG8gc3RvcmUgYSA2NGJpdCBiYXNlIDEyOCB2YXJpYWJsZS1sZW5ndGggaW50ZWdlci5cclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gdmFsdWUgVmFsdWUgdG8gZW5jb2RlXHJcbiAgICAgICAgICogQHJldHVybnMge251bWJlcn0gTnVtYmVyIG9mIGJ5dGVzIHJlcXVpcmVkLiBDYXBwZWQgdG8ge0BsaW5rIEJ5dGVCdWZmZXIuTUFYX1ZBUklOVDY0X0JZVEVTfVxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKi9cclxuICAgICAgICBCeXRlQnVmZmVyLmNhbGN1bGF0ZVZhcmludDY0ID0gZnVuY3Rpb24odmFsdWUpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBMb25nLmZyb21OdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJylcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IExvbmcuZnJvbVN0cmluZyh2YWx1ZSk7XG4gICAgICAgICAgICAvLyByZWY6IHNyYy9nb29nbGUvcHJvdG9idWYvaW8vY29kZWRfc3RyZWFtLmNjXHJcbiAgICAgICAgICAgIHZhciBwYXJ0MCA9IHZhbHVlLnRvSW50KCkgPj4+IDAsXHJcbiAgICAgICAgICAgICAgICBwYXJ0MSA9IHZhbHVlLnNoaWZ0UmlnaHRVbnNpZ25lZCgyOCkudG9JbnQoKSA+Pj4gMCxcclxuICAgICAgICAgICAgICAgIHBhcnQyID0gdmFsdWUuc2hpZnRSaWdodFVuc2lnbmVkKDU2KS50b0ludCgpID4+PiAwO1xyXG4gICAgICAgICAgICBpZiAocGFydDIgPT0gMCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHBhcnQxID09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocGFydDAgPCAxIDw8IDE0KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFydDAgPCAxIDw8IDcgPyAxIDogMjtcclxuICAgICAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBwYXJ0MCA8IDEgPDwgMjEgPyAzIDogNDtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHBhcnQxIDwgMSA8PCAxNClcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHBhcnQxIDwgMSA8PCA3ID8gNSA6IDY7XHJcbiAgICAgICAgICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gcGFydDEgPCAxIDw8IDIxID8gNyA6IDg7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHBhcnQyIDwgMSA8PCA3ID8gOSA6IDEwO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFppZ3phZyBlbmNvZGVzIGEgc2lnbmVkIDY0Yml0IGludGVnZXIgc28gdGhhdCBpdCBjYW4gYmUgZWZmZWN0aXZlbHkgdXNlZCB3aXRoIHZhcmludCBlbmNvZGluZy5cclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gdmFsdWUgU2lnbmVkIGxvbmdcclxuICAgICAgICAgKiBAcmV0dXJucyB7IUxvbmd9IFVuc2lnbmVkIHppZ3phZyBlbmNvZGVkIGxvbmdcclxuICAgICAgICAgKiBAZXhwb3NlXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgQnl0ZUJ1ZmZlci56aWdaYWdFbmNvZGU2NCA9IGZ1bmN0aW9uKHZhbHVlKSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKVxuICAgICAgICAgICAgICAgIHZhbHVlID0gTG9uZy5mcm9tTnVtYmVyKHZhbHVlLCBmYWxzZSk7XG4gICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKVxuICAgICAgICAgICAgICAgIHZhbHVlID0gTG9uZy5mcm9tU3RyaW5nKHZhbHVlLCBmYWxzZSk7XG4gICAgICAgICAgICBlbHNlIGlmICh2YWx1ZS51bnNpZ25lZCAhPT0gZmFsc2UpIHZhbHVlID0gdmFsdWUudG9TaWduZWQoKTtcbiAgICAgICAgICAgIC8vIHJlZjogc3JjL2dvb2dsZS9wcm90b2J1Zi93aXJlX2Zvcm1hdF9saXRlLmhcclxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlLnNoaWZ0TGVmdCgxKS54b3IodmFsdWUuc2hpZnRSaWdodCg2MykpLnRvVW5zaWduZWQoKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBEZWNvZGVzIGEgemlnemFnIGVuY29kZWQgc2lnbmVkIDY0Yml0IGludGVnZXIuXHJcbiAgICAgICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ9IHZhbHVlIFVuc2lnbmVkIHppZ3phZyBlbmNvZGVkIGxvbmcgb3IgSmF2YVNjcmlwdCBudW1iZXJcclxuICAgICAgICAgKiBAcmV0dXJucyB7IUxvbmd9IFNpZ25lZCBsb25nXHJcbiAgICAgICAgICogQGV4cG9zZVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIEJ5dGVCdWZmZXIuemlnWmFnRGVjb2RlNjQgPSBmdW5jdGlvbih2YWx1ZSkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJylcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IExvbmcuZnJvbU51bWJlcih2YWx1ZSwgZmFsc2UpO1xuICAgICAgICAgICAgZWxzZSBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJylcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IExvbmcuZnJvbVN0cmluZyh2YWx1ZSwgZmFsc2UpO1xuICAgICAgICAgICAgZWxzZSBpZiAodmFsdWUudW5zaWduZWQgIT09IGZhbHNlKSB2YWx1ZSA9IHZhbHVlLnRvU2lnbmVkKCk7XG4gICAgICAgICAgICAvLyByZWY6IHNyYy9nb29nbGUvcHJvdG9idWYvd2lyZV9mb3JtYXRfbGl0ZS5oXHJcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZS5zaGlmdFJpZ2h0VW5zaWduZWQoMSkueG9yKHZhbHVlLmFuZChMb25nLk9ORSkudG9TaWduZWQoKS5uZWdhdGUoKSkudG9TaWduZWQoKTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBXcml0ZXMgYSA2NGJpdCBiYXNlIDEyOCB2YXJpYWJsZS1sZW5ndGggaW50ZWdlci5cclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcnxMb25nfSB2YWx1ZSBWYWx1ZSB0byB3cml0ZVxyXG4gICAgICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgdGhlIG51bWJlciBvZiBieXRlc1xyXG4gICAgICAgICAqICB3cml0dGVuIGlmIG9taXR0ZWQuXHJcbiAgICAgICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfG51bWJlcn0gYHRoaXNgIGlmIG9mZnNldCBpcyBvbWl0dGVkLCBlbHNlIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGJ5dGVzIHdyaXR0ZW4uXHJcbiAgICAgICAgICogQGV4cG9zZVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVWYXJpbnQ2NCA9IGZ1bmN0aW9uKHZhbHVlLCBvZmZzZXQpIHtcclxuICAgICAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJylcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBMb25nLmZyb21OdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gTG9uZy5mcm9tU3RyaW5nKHZhbHVlKTtcbiAgICAgICAgICAgICAgICBlbHNlIGlmICghKHZhbHVlICYmIHZhbHVlIGluc3RhbmNlb2YgTG9uZykpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgdmFsdWU6IFwiK3ZhbHVlK1wiIChub3QgYW4gaW50ZWdlciBvciBMb25nKVwiKTtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIiswK1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBMb25nLmZyb21OdW1iZXIodmFsdWUsIGZhbHNlKTtcbiAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpXG4gICAgICAgICAgICAgICAgdmFsdWUgPSBMb25nLmZyb21TdHJpbmcodmFsdWUsIGZhbHNlKTtcbiAgICAgICAgICAgIGVsc2UgaWYgKHZhbHVlLnVuc2lnbmVkICE9PSBmYWxzZSkgdmFsdWUgPSB2YWx1ZS50b1NpZ25lZCgpO1xuICAgICAgICAgICAgdmFyIHNpemUgPSBCeXRlQnVmZmVyLmNhbGN1bGF0ZVZhcmludDY0KHZhbHVlKSxcclxuICAgICAgICAgICAgICAgIHBhcnQwID0gdmFsdWUudG9JbnQoKSA+Pj4gMCxcclxuICAgICAgICAgICAgICAgIHBhcnQxID0gdmFsdWUuc2hpZnRSaWdodFVuc2lnbmVkKDI4KS50b0ludCgpID4+PiAwLFxyXG4gICAgICAgICAgICAgICAgcGFydDIgPSB2YWx1ZS5zaGlmdFJpZ2h0VW5zaWduZWQoNTYpLnRvSW50KCkgPj4+IDA7XHJcbiAgICAgICAgICAgIG9mZnNldCArPSBzaXplO1xuICAgICAgICAgICAgdmFyIGNhcGFjaXR5MTEgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA+IGNhcGFjaXR5MTEpXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemUoKGNhcGFjaXR5MTEgKj0gMikgPiBvZmZzZXQgPyBjYXBhY2l0eTExIDogb2Zmc2V0KTtcbiAgICAgICAgICAgIG9mZnNldCAtPSBzaXplO1xuICAgICAgICAgICAgc3dpdGNoIChzaXplKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDEwOiB0aGlzLnZpZXdbb2Zmc2V0KzldID0gKHBhcnQyID4+PiAgNykgJiAweDAxO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA5IDogdGhpcy52aWV3W29mZnNldCs4XSA9IHNpemUgIT09IDkgPyAocGFydDIgICAgICAgKSB8IDB4ODAgOiAocGFydDIgICAgICAgKSAmIDB4N0Y7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDggOiB0aGlzLnZpZXdbb2Zmc2V0KzddID0gc2l6ZSAhPT0gOCA/IChwYXJ0MSA+Pj4gMjEpIHwgMHg4MCA6IChwYXJ0MSA+Pj4gMjEpICYgMHg3RjtcclxuICAgICAgICAgICAgICAgIGNhc2UgNyA6IHRoaXMudmlld1tvZmZzZXQrNl0gPSBzaXplICE9PSA3ID8gKHBhcnQxID4+PiAxNCkgfCAweDgwIDogKHBhcnQxID4+PiAxNCkgJiAweDdGO1xyXG4gICAgICAgICAgICAgICAgY2FzZSA2IDogdGhpcy52aWV3W29mZnNldCs1XSA9IHNpemUgIT09IDYgPyAocGFydDEgPj4+ICA3KSB8IDB4ODAgOiAocGFydDEgPj4+ICA3KSAmIDB4N0Y7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDUgOiB0aGlzLnZpZXdbb2Zmc2V0KzRdID0gc2l6ZSAhPT0gNSA/IChwYXJ0MSAgICAgICApIHwgMHg4MCA6IChwYXJ0MSAgICAgICApICYgMHg3RjtcclxuICAgICAgICAgICAgICAgIGNhc2UgNCA6IHRoaXMudmlld1tvZmZzZXQrM10gPSBzaXplICE9PSA0ID8gKHBhcnQwID4+PiAyMSkgfCAweDgwIDogKHBhcnQwID4+PiAyMSkgJiAweDdGO1xyXG4gICAgICAgICAgICAgICAgY2FzZSAzIDogdGhpcy52aWV3W29mZnNldCsyXSA9IHNpemUgIT09IDMgPyAocGFydDAgPj4+IDE0KSB8IDB4ODAgOiAocGFydDAgPj4+IDE0KSAmIDB4N0Y7XHJcbiAgICAgICAgICAgICAgICBjYXNlIDIgOiB0aGlzLnZpZXdbb2Zmc2V0KzFdID0gc2l6ZSAhPT0gMiA/IChwYXJ0MCA+Pj4gIDcpIHwgMHg4MCA6IChwYXJ0MCA+Pj4gIDcpICYgMHg3RjtcclxuICAgICAgICAgICAgICAgIGNhc2UgMSA6IHRoaXMudmlld1tvZmZzZXQgIF0gPSBzaXplICE9PSAxID8gKHBhcnQwICAgICAgICkgfCAweDgwIDogKHBhcnQwICAgICAgICkgJiAweDdGO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5vZmZzZXQgKz0gc2l6ZTtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHNpemU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBXcml0ZXMgYSB6aWctemFnIGVuY29kZWQgNjRiaXQgYmFzZSAxMjggdmFyaWFibGUtbGVuZ3RoIGludGVnZXIuXHJcbiAgICAgICAgICogQHBhcmFtIHtudW1iZXJ8TG9uZ30gdmFsdWUgVmFsdWUgdG8gd3JpdGVcclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IHRoZSBudW1iZXIgb2YgYnl0ZXNcclxuICAgICAgICAgKiAgd3JpdHRlbiBpZiBvbWl0dGVkLlxyXG4gICAgICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcnxudW1iZXJ9IGB0aGlzYCBpZiBvZmZzZXQgaXMgb21pdHRlZCwgZWxzZSB0aGUgYWN0dWFsIG51bWJlciBvZiBieXRlcyB3cml0dGVuLlxyXG4gICAgICAgICAqIEBleHBvc2VcclxuICAgICAgICAgKi9cclxuICAgICAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlVmFyaW50NjRaaWdaYWcgPSBmdW5jdGlvbih2YWx1ZSwgb2Zmc2V0KSB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLndyaXRlVmFyaW50NjQoQnl0ZUJ1ZmZlci56aWdaYWdFbmNvZGU2NCh2YWx1ZSksIG9mZnNldCk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogUmVhZHMgYSA2NGJpdCBiYXNlIDEyOCB2YXJpYWJsZS1sZW5ndGggaW50ZWdlci4gUmVxdWlyZXMgTG9uZy5qcy5cclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSB0aGUgbnVtYmVyIG9mIGJ5dGVzXHJcbiAgICAgICAgICogIHJlYWQgaWYgb21pdHRlZC5cclxuICAgICAgICAgKiBAcmV0dXJucyB7IUxvbmd8IXt2YWx1ZTogTG9uZywgbGVuZ3RoOiBudW1iZXJ9fSBUaGUgdmFsdWUgcmVhZCBpZiBvZmZzZXQgaXMgb21pdHRlZCwgZWxzZSB0aGUgdmFsdWUgcmVhZCBhbmRcclxuICAgICAgICAgKiAgdGhlIGFjdHVhbCBudW1iZXIgb2YgYnl0ZXMgcmVhZC5cclxuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgaXQncyBub3QgYSB2YWxpZCB2YXJpbnRcclxuICAgICAgICAgKiBAZXhwb3NlXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVmFyaW50NjQgPSBmdW5jdGlvbihvZmZzZXQpIHtcclxuICAgICAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMSA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIisxK1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gcmVmOiBzcmMvZ29vZ2xlL3Byb3RvYnVmL2lvL2NvZGVkX3N0cmVhbS5jY1xyXG4gICAgICAgICAgICB2YXIgc3RhcnQgPSBvZmZzZXQsXHJcbiAgICAgICAgICAgICAgICBwYXJ0MCA9IDAsXHJcbiAgICAgICAgICAgICAgICBwYXJ0MSA9IDAsXHJcbiAgICAgICAgICAgICAgICBwYXJ0MiA9IDAsXHJcbiAgICAgICAgICAgICAgICBiICA9IDA7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MCAgPSAoYiAmIDB4N0YpICAgICAgOyBpZiAoIGIgJiAweDgwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MCB8PSAoYiAmIDB4N0YpIDw8ICA3OyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MCB8PSAoYiAmIDB4N0YpIDw8IDE0OyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MCB8PSAoYiAmIDB4N0YpIDw8IDIxOyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MSAgPSAoYiAmIDB4N0YpICAgICAgOyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MSB8PSAoYiAmIDB4N0YpIDw8ICA3OyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MSB8PSAoYiAmIDB4N0YpIDw8IDE0OyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MSB8PSAoYiAmIDB4N0YpIDw8IDIxOyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MiAgPSAoYiAmIDB4N0YpICAgICAgOyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbb2Zmc2V0KytdOyBwYXJ0MiB8PSAoYiAmIDB4N0YpIDw8ICA3OyBpZiAoKGIgJiAweDgwKSB8fCAodGhpcy5ub0Fzc2VydCAmJiB0eXBlb2YgYiA9PT0gJ3VuZGVmaW5lZCcpKSB7XHJcbiAgICAgICAgICAgIHRocm93IEVycm9yKFwiQnVmZmVyIG92ZXJydW5cIik7IH19fX19fX19fX1cclxuICAgICAgICAgICAgdmFyIHZhbHVlID0gTG9uZy5mcm9tQml0cyhwYXJ0MCB8IChwYXJ0MSA8PCAyOCksIChwYXJ0MSA+Pj4gNCkgfCAocGFydDIpIDw8IDI0LCBmYWxzZSk7XHJcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdmFsdWU7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgICAgICd2YWx1ZSc6IHZhbHVlLFxyXG4gICAgICAgICAgICAgICAgICAgICdsZW5ndGgnOiBvZmZzZXQtc3RhcnRcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBSZWFkcyBhIHppZy16YWcgZW5jb2RlZCA2NGJpdCBiYXNlIDEyOCB2YXJpYWJsZS1sZW5ndGggaW50ZWdlci4gUmVxdWlyZXMgTG9uZy5qcy5cclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSB0aGUgbnVtYmVyIG9mIGJ5dGVzXHJcbiAgICAgICAgICogIHJlYWQgaWYgb21pdHRlZC5cclxuICAgICAgICAgKiBAcmV0dXJucyB7IUxvbmd8IXt2YWx1ZTogTG9uZywgbGVuZ3RoOiBudW1iZXJ9fSBUaGUgdmFsdWUgcmVhZCBpZiBvZmZzZXQgaXMgb21pdHRlZCwgZWxzZSB0aGUgdmFsdWUgcmVhZCBhbmRcclxuICAgICAgICAgKiAgdGhlIGFjdHVhbCBudW1iZXIgb2YgYnl0ZXMgcmVhZC5cclxuICAgICAgICAgKiBAdGhyb3dzIHtFcnJvcn0gSWYgaXQncyBub3QgYSB2YWxpZCB2YXJpbnRcclxuICAgICAgICAgKiBAZXhwb3NlXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVmFyaW50NjRaaWdaYWcgPSBmdW5jdGlvbihvZmZzZXQpIHtcclxuICAgICAgICAgICAgdmFyIHZhbCA9IHRoaXMucmVhZFZhcmludDY0KG9mZnNldCk7XHJcbiAgICAgICAgICAgIGlmICh2YWwgJiYgdmFsWyd2YWx1ZSddIGluc3RhbmNlb2YgTG9uZylcclxuICAgICAgICAgICAgICAgIHZhbFtcInZhbHVlXCJdID0gQnl0ZUJ1ZmZlci56aWdaYWdEZWNvZGU2NCh2YWxbXCJ2YWx1ZVwiXSk7XHJcbiAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgIHZhbCA9IEJ5dGVCdWZmZXIuemlnWmFnRGVjb2RlNjQodmFsKTtcclxuICAgICAgICAgICAgcmV0dXJuIHZhbDtcclxuICAgICAgICB9O1xyXG5cclxuICAgIH0gLy8gTG9uZ1xyXG5cclxuXHJcbiAgICAvLyB0eXBlcy9zdHJpbmdzL2NzdHJpbmdcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdyaXRlcyBhIE5VTEwtdGVybWluYXRlZCBVVEY4IGVuY29kZWQgc3RyaW5nLiBGb3IgdGhpcyB0byB3b3JrIHRoZSBzcGVjaWZpZWQgc3RyaW5nIG11c3Qgbm90IGNvbnRhaW4gYW55IE5VTExcclxuICAgICAqICBjaGFyYWN0ZXJzIGl0c2VsZi5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgU3RyaW5nIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IHRoZSBudW1iZXIgb2YgYnl0ZXNcclxuICAgICAqICBjb250YWluZWQgaW4gYHN0cmAgKyAxIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ8bnVtYmVyfSB0aGlzIGlmIG9mZnNldCBpcyBvbWl0dGVkLCBlbHNlIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGJ5dGVzIHdyaXR0ZW5cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZUNTdHJpbmcgPSBmdW5jdGlvbihzdHIsIG9mZnNldCkge1xyXG4gICAgICAgIHZhciByZWxhdGl2ZSA9IHR5cGVvZiBvZmZzZXQgPT09ICd1bmRlZmluZWQnO1xuICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICB2YXIgaSxcclxuICAgICAgICAgICAgayA9IHN0ci5sZW5ndGg7XHJcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgc3RyOiBOb3QgYSBzdHJpbmdcIik7XHJcbiAgICAgICAgICAgIGZvciAoaT0wOyBpPGs7ICsraSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHN0ci5jaGFyQ29kZUF0KGkpID09PSAwKVxyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIHN0cjogQ29udGFpbnMgTlVMTC1jaGFyYWN0ZXJzXCIpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICAvLyBVVEY4IHN0cmluZ3MgZG8gbm90IGNvbnRhaW4gemVybyBieXRlcyBpbiBiZXR3ZWVuIGV4Y2VwdCBmb3IgdGhlIHplcm8gY2hhcmFjdGVyLCBzbzpcclxuICAgICAgICBrID0gdXRmeC5jYWxjdWxhdGVVVEYxNmFzVVRGOChzdHJpbmdTb3VyY2Uoc3RyKSlbMV07XHJcbiAgICAgICAgb2Zmc2V0ICs9IGsrMTtcbiAgICAgICAgdmFyIGNhcGFjaXR5MTIgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAob2Zmc2V0ID4gY2FwYWNpdHkxMilcbiAgICAgICAgICAgIHRoaXMucmVzaXplKChjYXBhY2l0eTEyICo9IDIpID4gb2Zmc2V0ID8gY2FwYWNpdHkxMiA6IG9mZnNldCk7XG4gICAgICAgIG9mZnNldCAtPSBrKzE7XG4gICAgICAgIHV0ZnguZW5jb2RlVVRGMTZ0b1VURjgoc3RyaW5nU291cmNlKHN0ciksIGZ1bmN0aW9uKGIpIHtcclxuICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsrXSA9IGI7XHJcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcclxuICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KytdID0gMDtcclxuICAgICAgICBpZiAocmVsYXRpdmUpIHtcclxuICAgICAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gaztcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhIE5VTEwtdGVybWluYXRlZCBVVEY4IGVuY29kZWQgc3RyaW5nLiBGb3IgdGhpcyB0byB3b3JrIHRoZSBzdHJpbmcgcmVhZCBtdXN0IG5vdCBjb250YWluIGFueSBOVUxMIGNoYXJhY3RlcnNcclxuICAgICAqICBpdHNlbGYuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSB0aGUgbnVtYmVyIG9mIGJ5dGVzXHJcbiAgICAgKiAgcmVhZCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMge3N0cmluZ3whe3N0cmluZzogc3RyaW5nLCBsZW5ndGg6IG51bWJlcn19IFRoZSBzdHJpbmcgcmVhZCBpZiBvZmZzZXQgaXMgb21pdHRlZCwgZWxzZSB0aGUgc3RyaW5nXHJcbiAgICAgKiAgcmVhZCBhbmQgdGhlIGFjdHVhbCBudW1iZXIgb2YgYnl0ZXMgcmVhZC5cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkQ1N0cmluZyA9IGZ1bmN0aW9uKG9mZnNldCkge1xyXG4gICAgICAgIHZhciByZWxhdGl2ZSA9IHR5cGVvZiBvZmZzZXQgPT09ICd1bmRlZmluZWQnO1xuICAgICAgICBpZiAocmVsYXRpdmUpIG9mZnNldCA9IHRoaXMub2Zmc2V0O1xuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInIHx8IG9mZnNldCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgb2Zmc2V0ID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCArIDEgPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIisxK1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBzdGFydCA9IG9mZnNldCxcclxuICAgICAgICAgICAgdGVtcDtcclxuICAgICAgICAvLyBVVEY4IHN0cmluZ3MgZG8gbm90IGNvbnRhaW4gemVybyBieXRlcyBpbiBiZXR3ZWVuIGV4Y2VwdCBmb3IgdGhlIHplcm8gY2hhcmFjdGVyIGl0c2VsZiwgc286XHJcbiAgICAgICAgdmFyIHNkLCBiID0gLTE7XHJcbiAgICAgICAgdXRmeC5kZWNvZGVVVEY4dG9VVEYxNihmdW5jdGlvbigpIHtcclxuICAgICAgICAgICAgaWYgKGIgPT09IDApIHJldHVybiBudWxsO1xyXG4gICAgICAgICAgICBpZiAob2Zmc2V0ID49IHRoaXMubGltaXQpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCByYW5nZTogVHJ1bmNhdGVkIGRhdGEsIFwiK29mZnNldCtcIiA8IFwiK3RoaXMubGltaXQpO1xyXG4gICAgICAgICAgICBiID0gdGhpcy52aWV3W29mZnNldCsrXTtcclxuICAgICAgICAgICAgcmV0dXJuIGIgPT09IDAgPyBudWxsIDogYjtcclxuICAgICAgICB9LmJpbmQodGhpcyksIHNkID0gc3RyaW5nRGVzdGluYXRpb24oKSwgdHJ1ZSk7XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB7XHJcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0ID0gb2Zmc2V0O1xyXG4gICAgICAgICAgICByZXR1cm4gc2QoKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgXCJzdHJpbmdcIjogc2QoKSxcclxuICAgICAgICAgICAgICAgIFwibGVuZ3RoXCI6IG9mZnNldCAtIHN0YXJ0XHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgICAvLyB0eXBlcy9zdHJpbmdzL2lzdHJpbmdcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdyaXRlcyBhIGxlbmd0aCBhcyB1aW50MzIgcHJlZml4ZWQgVVRGOCBlbmNvZGVkIHN0cmluZy5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgU3RyaW5nIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IHRoZSBudW1iZXIgb2YgYnl0ZXNcclxuICAgICAqICB3cml0dGVuIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ8bnVtYmVyfSBgdGhpc2AgaWYgYG9mZnNldGAgaXMgb21pdHRlZCwgZWxzZSB0aGUgYWN0dWFsIG51bWJlciBvZiBieXRlcyB3cml0dGVuXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKiBAc2VlIEJ5dGVCdWZmZXIjd3JpdGVWYXJpbnQzMlxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLndyaXRlSVN0cmluZyA9IGZ1bmN0aW9uKHN0ciwgb2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHN0ciAhPT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIHN0cjogTm90IGEgc3RyaW5nXCIpO1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzArXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0YXJ0ID0gb2Zmc2V0LFxyXG4gICAgICAgICAgICBrO1xyXG4gICAgICAgIGsgPSB1dGZ4LmNhbGN1bGF0ZVVURjE2YXNVVEY4KHN0cmluZ1NvdXJjZShzdHIpLCB0aGlzLm5vQXNzZXJ0KVsxXTtcclxuICAgICAgICBvZmZzZXQgKz0gNCtrO1xuICAgICAgICB2YXIgY2FwYWNpdHkxMyA9IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICAgIGlmIChvZmZzZXQgPiBjYXBhY2l0eTEzKVxuICAgICAgICAgICAgdGhpcy5yZXNpemUoKGNhcGFjaXR5MTMgKj0gMikgPiBvZmZzZXQgPyBjYXBhY2l0eTEzIDogb2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0IC09IDQraztcbiAgICAgICAgaWYgKHRoaXMubGl0dGxlRW5kaWFuKSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzNdID0gKGsgPj4+IDI0KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzJdID0gKGsgPj4+IDE2KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzFdID0gKGsgPj4+ICA4KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0ICBdID0gIGsgICAgICAgICAmIDB4RkY7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0ICBdID0gKGsgPj4+IDI0KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzFdID0gKGsgPj4+IDE2KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzJdID0gKGsgPj4+ICA4KSAmIDB4RkY7XG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KzNdID0gIGsgICAgICAgICAmIDB4RkY7XG4gICAgICAgIH1cbiAgICAgICAgb2Zmc2V0ICs9IDQ7XHJcbiAgICAgICAgdXRmeC5lbmNvZGVVVEYxNnRvVVRGOChzdHJpbmdTb3VyY2Uoc3RyKSwgZnVuY3Rpb24oYikge1xyXG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KytdID0gYjtcclxuICAgICAgICB9LmJpbmQodGhpcykpO1xyXG4gICAgICAgIGlmIChvZmZzZXQgIT09IHN0YXJ0ICsgNCArIGspXHJcbiAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIHJhbmdlOiBUcnVuY2F0ZWQgZGF0YSwgXCIrb2Zmc2V0K1wiID09IFwiKyhvZmZzZXQrNCtrKSk7XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB7XHJcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0ID0gb2Zmc2V0O1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIG9mZnNldCAtIHN0YXJ0O1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlYWRzIGEgbGVuZ3RoIGFzIHVpbnQzMiBwcmVmaXhlZCBVVEY4IGVuY29kZWQgc3RyaW5nLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgdGhlIG51bWJlciBvZiBieXRlc1xyXG4gICAgICogIHJlYWQgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8IXtzdHJpbmc6IHN0cmluZywgbGVuZ3RoOiBudW1iZXJ9fSBUaGUgc3RyaW5nIHJlYWQgaWYgb2Zmc2V0IGlzIG9taXR0ZWQsIGVsc2UgdGhlIHN0cmluZ1xyXG4gICAgICogIHJlYWQgYW5kIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGJ5dGVzIHJlYWQuXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKiBAc2VlIEJ5dGVCdWZmZXIjcmVhZFZhcmludDMyXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZElTdHJpbmcgPSBmdW5jdGlvbihvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyA0ID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrNCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RhcnQgPSBvZmZzZXQ7XHJcbiAgICAgICAgdmFyIGxlbiA9IHRoaXMucmVhZFVpbnQzMihvZmZzZXQpO1xyXG4gICAgICAgIHZhciBzdHIgPSB0aGlzLnJlYWRVVEY4U3RyaW5nKGxlbiwgQnl0ZUJ1ZmZlci5NRVRSSUNTX0JZVEVTLCBvZmZzZXQgKz0gNCk7XHJcbiAgICAgICAgb2Zmc2V0ICs9IHN0clsnbGVuZ3RoJ107XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB7XHJcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0ID0gb2Zmc2V0O1xyXG4gICAgICAgICAgICByZXR1cm4gc3RyWydzdHJpbmcnXTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgJ3N0cmluZyc6IHN0clsnc3RyaW5nJ10sXHJcbiAgICAgICAgICAgICAgICAnbGVuZ3RoJzogb2Zmc2V0IC0gc3RhcnRcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIHR5cGVzL3N0cmluZ3MvdXRmOHN0cmluZ1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0cmljcyByZXByZXNlbnRpbmcgbnVtYmVyIG9mIFVURjggY2hhcmFjdGVycy4gRXZhbHVhdGVzIHRvIGBjYC5cclxuICAgICAqIEB0eXBlIHtzdHJpbmd9XHJcbiAgICAgKiBAY29uc3RcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlci5NRVRSSUNTX0NIQVJTID0gJ2MnO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWV0cmljcyByZXByZXNlbnRpbmcgbnVtYmVyIG9mIGJ5dGVzLiBFdmFsdWF0ZXMgdG8gYGJgLlxyXG4gICAgICogQHR5cGUge3N0cmluZ31cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLk1FVFJJQ1NfQllURVMgPSAnYic7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBXcml0ZXMgYW4gVVRGOCBlbmNvZGVkIHN0cmluZy5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgU3RyaW5nIHRvIHdyaXRlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gd3JpdGUgdG8uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ8bnVtYmVyfSB0aGlzIGlmIG9mZnNldCBpcyBvbWl0dGVkLCBlbHNlIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGJ5dGVzIHdyaXR0ZW4uXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVVVEY4U3RyaW5nID0gZnVuY3Rpb24oc3RyLCBvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICB2YXIgaztcclxuICAgICAgICB2YXIgc3RhcnQgPSBvZmZzZXQ7XHJcbiAgICAgICAgayA9IHV0ZnguY2FsY3VsYXRlVVRGMTZhc1VURjgoc3RyaW5nU291cmNlKHN0cikpWzFdO1xyXG4gICAgICAgIG9mZnNldCArPSBrO1xuICAgICAgICB2YXIgY2FwYWNpdHkxNCA9IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGg7XG4gICAgICAgIGlmIChvZmZzZXQgPiBjYXBhY2l0eTE0KVxuICAgICAgICAgICAgdGhpcy5yZXNpemUoKGNhcGFjaXR5MTQgKj0gMikgPiBvZmZzZXQgPyBjYXBhY2l0eTE0IDogb2Zmc2V0KTtcbiAgICAgICAgb2Zmc2V0IC09IGs7XG4gICAgICAgIHV0ZnguZW5jb2RlVVRGMTZ0b1VURjgoc3RyaW5nU291cmNlKHN0ciksIGZ1bmN0aW9uKGIpIHtcclxuICAgICAgICAgICAgdGhpcy52aWV3W29mZnNldCsrXSA9IGI7XHJcbiAgICAgICAgfS5iaW5kKHRoaXMpKTtcclxuICAgICAgICBpZiAocmVsYXRpdmUpIHtcclxuICAgICAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gb2Zmc2V0IC0gc3RhcnQ7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV3JpdGVzIGFuIFVURjggZW5jb2RlZCBzdHJpbmcuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIEJ5dGVCdWZmZXIjd3JpdGVVVEY4U3RyaW5nfS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciBTdHJpbmcgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcnxudW1iZXJ9IHRoaXMgaWYgb2Zmc2V0IGlzIG9taXR0ZWQsIGVsc2UgdGhlIGFjdHVhbCBudW1iZXIgb2YgYnl0ZXMgd3JpdHRlbi5cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS53cml0ZVN0cmluZyA9IEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVVVEY4U3RyaW5nO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgbnVtYmVyIG9mIFVURjggY2hhcmFjdGVycyBvZiBhIHN0cmluZy4gSmF2YVNjcmlwdCBpdHNlbGYgdXNlcyBVVEYtMTYsIHNvIHRoYXQgYSBzdHJpbmcnc1xyXG4gICAgICogIGBsZW5ndGhgIHByb3BlcnR5IGRvZXMgbm90IHJlZmxlY3QgaXRzIGFjdHVhbCBVVEY4IHNpemUgaWYgaXQgY29udGFpbnMgY29kZSBwb2ludHMgbGFyZ2VyIHRoYW4gMHhGRkZGLlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciBTdHJpbmcgdG8gY2FsY3VsYXRlXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1iZXIgb2YgVVRGOCBjaGFyYWN0ZXJzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuY2FsY3VsYXRlVVRGOENoYXJzID0gZnVuY3Rpb24oc3RyKSB7XHJcbiAgICAgICAgcmV0dXJuIHV0ZnguY2FsY3VsYXRlVVRGMTZhc1VURjgoc3RyaW5nU291cmNlKHN0cikpWzBdO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENhbGN1bGF0ZXMgdGhlIG51bWJlciBvZiBVVEY4IGJ5dGVzIG9mIGEgc3RyaW5nLlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciBTdHJpbmcgdG8gY2FsY3VsYXRlXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBOdW1iZXIgb2YgVVRGOCBieXRlc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLmNhbGN1bGF0ZVVURjhCeXRlcyA9IGZ1bmN0aW9uKHN0cikge1xyXG4gICAgICAgIHJldHVybiB1dGZ4LmNhbGN1bGF0ZVVURjE2YXNVVEY4KHN0cmluZ1NvdXJjZShzdHIpKVsxXTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxjdWxhdGVzIHRoZSBudW1iZXIgb2YgVVRGOCBieXRlcyBvZiBhIHN0cmluZy4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlci5jYWxjdWxhdGVVVEY4Qnl0ZXN9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFN0cmluZyB0byBjYWxjdWxhdGVcclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IE51bWJlciBvZiBVVEY4IGJ5dGVzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuY2FsY3VsYXRlU3RyaW5nID0gQnl0ZUJ1ZmZlci5jYWxjdWxhdGVVVEY4Qnl0ZXM7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZWFkcyBhbiBVVEY4IGVuY29kZWQgc3RyaW5nLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGxlbmd0aCBOdW1iZXIgb2YgY2hhcmFjdGVycyBvciBieXRlcyB0byByZWFkLlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmc9fSBtZXRyaWNzIE1ldHJpY3Mgc3BlY2lmeWluZyB3aGF0IGBsZW5ndGhgIGlzIG1lYW50IHRvIGNvdW50LiBEZWZhdWx0cyB0b1xyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyLk1FVFJJQ1NfQ0hBUlN9LlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHJlYWQgZnJvbS4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgdGhlIG51bWJlciBvZiBieXRlc1xyXG4gICAgICogIHJlYWQgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8IXtzdHJpbmc6IHN0cmluZywgbGVuZ3RoOiBudW1iZXJ9fSBUaGUgc3RyaW5nIHJlYWQgaWYgb2Zmc2V0IGlzIG9taXR0ZWQsIGVsc2UgdGhlIHN0cmluZ1xyXG4gICAgICogIHJlYWQgYW5kIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGJ5dGVzIHJlYWQuXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucmVhZFVURjhTdHJpbmcgPSBmdW5jdGlvbihsZW5ndGgsIG1ldHJpY3MsIG9mZnNldCkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgbWV0cmljcyA9PT0gJ251bWJlcicpIHtcclxuICAgICAgICAgICAgb2Zmc2V0ID0gbWV0cmljcztcclxuICAgICAgICAgICAgbWV0cmljcyA9IHVuZGVmaW5lZDtcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICh0eXBlb2YgbWV0cmljcyA9PT0gJ3VuZGVmaW5lZCcpIG1ldHJpY3MgPSBCeXRlQnVmZmVyLk1FVFJJQ1NfQ0hBUlM7XHJcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbGVuZ3RoICE9PSAnbnVtYmVyJyB8fCBsZW5ndGggJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgbGVuZ3RoOiBcIitsZW5ndGgrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIGxlbmd0aCB8PSAwO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInIHx8IG9mZnNldCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgb2Zmc2V0ID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCArIDAgPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogMCA8PSBcIitvZmZzZXQrXCIgKCtcIiswK1wiKSA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBpID0gMCxcclxuICAgICAgICAgICAgc3RhcnQgPSBvZmZzZXQsXHJcbiAgICAgICAgICAgIHNkO1xyXG4gICAgICAgIGlmIChtZXRyaWNzID09PSBCeXRlQnVmZmVyLk1FVFJJQ1NfQ0hBUlMpIHsgLy8gVGhlIHNhbWUgZm9yIG5vZGUgYW5kIHRoZSBicm93c2VyXHJcbiAgICAgICAgICAgIHNkID0gc3RyaW5nRGVzdGluYXRpb24oKTtcclxuICAgICAgICAgICAgdXRmeC5kZWNvZGVVVEY4KGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGkgPCBsZW5ndGggJiYgb2Zmc2V0IDwgdGhpcy5saW1pdCA/IHRoaXMudmlld1tvZmZzZXQrK10gOiBudWxsO1xyXG4gICAgICAgICAgICB9LmJpbmQodGhpcyksIGZ1bmN0aW9uKGNwKSB7XHJcbiAgICAgICAgICAgICAgICArK2k7IHV0ZnguVVRGOHRvVVRGMTYoY3AsIHNkKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGlmIChpICE9PSBsZW5ndGgpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCByYW5nZTogVHJ1bmNhdGVkIGRhdGEsIFwiK2krXCIgPT0gXCIrbGVuZ3RoKTtcclxuICAgICAgICAgICAgaWYgKHJlbGF0aXZlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9mZnNldCA9IG9mZnNldDtcclxuICAgICAgICAgICAgICAgIHJldHVybiBzZCgpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgICBcInN0cmluZ1wiOiBzZCgpLFxyXG4gICAgICAgICAgICAgICAgICAgIFwibGVuZ3RoXCI6IG9mZnNldCAtIHN0YXJ0XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIGlmIChtZXRyaWNzID09PSBCeXRlQnVmZmVyLk1FVFJJQ1NfQllURVMpIHtcclxuICAgICAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IFwiK29mZnNldCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgbGVuZ3RoID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiK2xlbmd0aCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHZhciBrID0gb2Zmc2V0ICsgbGVuZ3RoO1xyXG4gICAgICAgICAgICB1dGZ4LmRlY29kZVVURjh0b1VURjE2KGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG9mZnNldCA8IGsgPyB0aGlzLnZpZXdbb2Zmc2V0KytdIDogbnVsbDtcclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLCBzZCA9IHN0cmluZ0Rlc3RpbmF0aW9uKCksIHRoaXMubm9Bc3NlcnQpO1xyXG4gICAgICAgICAgICBpZiAob2Zmc2V0ICE9PSBrKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgcmFuZ2U6IFRydW5jYXRlZCBkYXRhLCBcIitvZmZzZXQrXCIgPT0gXCIrayk7XHJcbiAgICAgICAgICAgIGlmIChyZWxhdGl2ZSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gc2QoKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICAgICAgJ3N0cmluZyc6IHNkKCksXHJcbiAgICAgICAgICAgICAgICAgICAgJ2xlbmd0aCc6IG9mZnNldCAtIHN0YXJ0XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlXHJcbiAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIlVuc3VwcG9ydGVkIG1ldHJpY3M6IFwiK21ldHJpY3MpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlYWRzIGFuIFVURjggZW5jb2RlZCBzdHJpbmcuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIEJ5dGVCdWZmZXIjcmVhZFVURjhTdHJpbmd9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGVuZ3RoIE51bWJlciBvZiBjaGFyYWN0ZXJzIG9yIGJ5dGVzIHRvIHJlYWRcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gbWV0cmljcyBNZXRyaWNzIHNwZWNpZnlpbmcgd2hhdCBgbmAgaXMgbWVhbnQgdG8gY291bnQuIERlZmF1bHRzIHRvXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIuTUVUUklDU19DSEFSU30uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gcmVhZCBmcm9tLiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSB0aGUgbnVtYmVyIG9mIGJ5dGVzXHJcbiAgICAgKiAgcmVhZCBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMge3N0cmluZ3whe3N0cmluZzogc3RyaW5nLCBsZW5ndGg6IG51bWJlcn19IFRoZSBzdHJpbmcgcmVhZCBpZiBvZmZzZXQgaXMgb21pdHRlZCwgZWxzZSB0aGUgc3RyaW5nXHJcbiAgICAgKiAgcmVhZCBhbmQgdGhlIGFjdHVhbCBudW1iZXIgb2YgYnl0ZXMgcmVhZC5cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkU3RyaW5nID0gQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZWFkVVRGOFN0cmluZztcclxuXHJcbiAgICAvLyB0eXBlcy9zdHJpbmdzL3ZzdHJpbmdcclxuXHJcbiAgICAvKipcclxuICAgICAqIFdyaXRlcyBhIGxlbmd0aCBhcyB2YXJpbnQzMiBwcmVmaXhlZCBVVEY4IGVuY29kZWQgc3RyaW5nLlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciBTdHJpbmcgdG8gd3JpdGVcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byB3cml0ZSB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgdGhlIG51bWJlciBvZiBieXRlc1xyXG4gICAgICogIHdyaXR0ZW4gaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcnxudW1iZXJ9IGB0aGlzYCBpZiBgb2Zmc2V0YCBpcyBvbWl0dGVkLCBlbHNlIHRoZSBhY3R1YWwgbnVtYmVyIG9mIGJ5dGVzIHdyaXR0ZW5cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqIEBzZWUgQnl0ZUJ1ZmZlciN3cml0ZVZhcmludDMyXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUud3JpdGVWU3RyaW5nID0gZnVuY3Rpb24oc3RyLCBvZmZzZXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJylcclxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgc3RyOiBOb3QgYSBzdHJpbmdcIik7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICB2YXIgc3RhcnQgPSBvZmZzZXQsXHJcbiAgICAgICAgICAgIGssIGw7XHJcbiAgICAgICAgayA9IHV0ZnguY2FsY3VsYXRlVVRGMTZhc1VURjgoc3RyaW5nU291cmNlKHN0ciksIHRoaXMubm9Bc3NlcnQpWzFdO1xyXG4gICAgICAgIGwgPSBCeXRlQnVmZmVyLmNhbGN1bGF0ZVZhcmludDMyKGspO1xyXG4gICAgICAgIG9mZnNldCArPSBsK2s7XG4gICAgICAgIHZhciBjYXBhY2l0eTE1ID0gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aDtcbiAgICAgICAgaWYgKG9mZnNldCA+IGNhcGFjaXR5MTUpXG4gICAgICAgICAgICB0aGlzLnJlc2l6ZSgoY2FwYWNpdHkxNSAqPSAyKSA+IG9mZnNldCA/IGNhcGFjaXR5MTUgOiBvZmZzZXQpO1xuICAgICAgICBvZmZzZXQgLT0gbCtrO1xuICAgICAgICBvZmZzZXQgKz0gdGhpcy53cml0ZVZhcmludDMyKGssIG9mZnNldCk7XHJcbiAgICAgICAgdXRmeC5lbmNvZGVVVEYxNnRvVVRGOChzdHJpbmdTb3VyY2Uoc3RyKSwgZnVuY3Rpb24oYikge1xyXG4gICAgICAgICAgICB0aGlzLnZpZXdbb2Zmc2V0KytdID0gYjtcclxuICAgICAgICB9LmJpbmQodGhpcykpO1xyXG4gICAgICAgIGlmIChvZmZzZXQgIT09IHN0YXJ0K2srbClcclxuICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgcmFuZ2U6IFRydW5jYXRlZCBkYXRhLCBcIitvZmZzZXQrXCIgPT0gXCIrKG9mZnNldCtrK2wpKTtcclxuICAgICAgICBpZiAocmVsYXRpdmUpIHtcclxuICAgICAgICAgICAgdGhpcy5vZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gb2Zmc2V0IC0gc3RhcnQ7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZHMgYSBsZW5ndGggYXMgdmFyaW50MzIgcHJlZml4ZWQgVVRGOCBlbmNvZGVkIHN0cmluZy5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byByZWFkIGZyb20uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IHRoZSBudW1iZXIgb2YgYnl0ZXNcclxuICAgICAqICByZWFkIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfCF7c3RyaW5nOiBzdHJpbmcsIGxlbmd0aDogbnVtYmVyfX0gVGhlIHN0cmluZyByZWFkIGlmIG9mZnNldCBpcyBvbWl0dGVkLCBlbHNlIHRoZSBzdHJpbmdcclxuICAgICAqICByZWFkIGFuZCB0aGUgYWN0dWFsIG51bWJlciBvZiBieXRlcyByZWFkLlxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICogQHNlZSBCeXRlQnVmZmVyI3JlYWRWYXJpbnQzMlxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnJlYWRWU3RyaW5nID0gZnVuY3Rpb24ob2Zmc2V0KSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIG9mZnNldCA9PT0gJ3VuZGVmaW5lZCc7XG4gICAgICAgIGlmIChyZWxhdGl2ZSkgb2Zmc2V0ID0gdGhpcy5vZmZzZXQ7XG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMSA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzErXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHN0YXJ0ID0gb2Zmc2V0O1xyXG4gICAgICAgIHZhciBsZW4gPSB0aGlzLnJlYWRWYXJpbnQzMihvZmZzZXQpO1xyXG4gICAgICAgIHZhciBzdHIgPSB0aGlzLnJlYWRVVEY4U3RyaW5nKGxlblsndmFsdWUnXSwgQnl0ZUJ1ZmZlci5NRVRSSUNTX0JZVEVTLCBvZmZzZXQgKz0gbGVuWydsZW5ndGgnXSk7XHJcbiAgICAgICAgb2Zmc2V0ICs9IHN0clsnbGVuZ3RoJ107XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB7XHJcbiAgICAgICAgICAgIHRoaXMub2Zmc2V0ID0gb2Zmc2V0O1xyXG4gICAgICAgICAgICByZXR1cm4gc3RyWydzdHJpbmcnXTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgJ3N0cmluZyc6IHN0clsnc3RyaW5nJ10sXHJcbiAgICAgICAgICAgICAgICAnbGVuZ3RoJzogb2Zmc2V0IC0gc3RhcnRcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICB9O1xyXG5cclxuXHJcbiAgICAvKipcclxuICAgICAqIEFwcGVuZHMgc29tZSBkYXRhIHRvIHRoaXMgQnl0ZUJ1ZmZlci4gVGhpcyB3aWxsIG92ZXJ3cml0ZSBhbnkgY29udGVudHMgYmVoaW5kIHRoZSBzcGVjaWZpZWQgb2Zmc2V0IHVwIHRvIHRoZSBhcHBlbmRlZFxyXG4gICAgICogIGRhdGEncyBsZW5ndGguXHJcbiAgICAgKiBAcGFyYW0geyFCeXRlQnVmZmVyfCFBcnJheUJ1ZmZlcnwhVWludDhBcnJheXxzdHJpbmd9IHNvdXJjZSBEYXRhIHRvIGFwcGVuZC4gSWYgYHNvdXJjZWAgaXMgYSBCeXRlQnVmZmVyLCBpdHMgb2Zmc2V0c1xyXG4gICAgICogIHdpbGwgYmUgbW9kaWZpZWQgYWNjb3JkaW5nIHRvIHRoZSBwZXJmb3JtZWQgcmVhZCBvcGVyYXRpb24uXHJcbiAgICAgKiBAcGFyYW0geyhzdHJpbmd8bnVtYmVyKT19IGVuY29kaW5nIEVuY29kaW5nIGlmIGBkYXRhYCBpcyBhIHN0cmluZyAoXCJiYXNlNjRcIiwgXCJoZXhcIiwgXCJiaW5hcnlcIiwgZGVmYXVsdHMgdG8gXCJ1dGY4XCIpXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gYXBwZW5kIGF0LiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSB0aGUgbnVtYmVyIG9mIGJ5dGVzXHJcbiAgICAgKiAgd3JpdHRlbiBpZiBvbWl0dGVkLlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKiBAZXhhbXBsZSBBIHJlbGF0aXZlIGA8MDEgMDI+MDMuYXBwZW5kKDwwNCAwNT4pYCB3aWxsIHJlc3VsdCBpbiBgPDAxIDAyIDA0IDA1PiwgMDQgMDV8YFxyXG4gICAgICogQGV4YW1wbGUgQW4gYWJzb2x1dGUgYDwwMSAwMj4wMy5hcHBlbmQoMDQgMDU+LCAxKWAgd2lsbCByZXN1bHQgaW4gYDwwMSAwND4wNSwgMDQgMDV8YFxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLmFwcGVuZCA9IGZ1bmN0aW9uKHNvdXJjZSwgZW5jb2RpbmcsIG9mZnNldCkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdudW1iZXInIHx8IHR5cGVvZiBlbmNvZGluZyAhPT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgb2Zmc2V0ID0gZW5jb2Rpbmc7XHJcbiAgICAgICAgICAgIGVuY29kaW5nID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIShzb3VyY2UgaW5zdGFuY2VvZiBCeXRlQnVmZmVyKSlcclxuICAgICAgICAgICAgc291cmNlID0gQnl0ZUJ1ZmZlci53cmFwKHNvdXJjZSwgZW5jb2RpbmcpO1xyXG4gICAgICAgIHZhciBsZW5ndGggPSBzb3VyY2UubGltaXQgLSBzb3VyY2Uub2Zmc2V0O1xyXG4gICAgICAgIGlmIChsZW5ndGggPD0gMCkgcmV0dXJuIHRoaXM7IC8vIE5vdGhpbmcgdG8gYXBwZW5kXHJcbiAgICAgICAgb2Zmc2V0ICs9IGxlbmd0aDtcbiAgICAgICAgdmFyIGNhcGFjaXR5MTYgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xuICAgICAgICBpZiAob2Zmc2V0ID4gY2FwYWNpdHkxNilcbiAgICAgICAgICAgIHRoaXMucmVzaXplKChjYXBhY2l0eTE2ICo9IDIpID4gb2Zmc2V0ID8gY2FwYWNpdHkxNiA6IG9mZnNldCk7XG4gICAgICAgIG9mZnNldCAtPSBsZW5ndGg7XG4gICAgICAgIHRoaXMudmlldy5zZXQoc291cmNlLnZpZXcuc3ViYXJyYXkoc291cmNlLm9mZnNldCwgc291cmNlLmxpbWl0KSwgb2Zmc2V0KTtcclxuICAgICAgICBzb3VyY2Uub2Zmc2V0ICs9IGxlbmd0aDtcclxuICAgICAgICBpZiAocmVsYXRpdmUpIHRoaXMub2Zmc2V0ICs9IGxlbmd0aDtcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQXBwZW5kcyB0aGlzIEJ5dGVCdWZmZXIncyBjb250ZW50cyB0byBhbm90aGVyIEJ5dGVCdWZmZXIuIFRoaXMgd2lsbCBvdmVyd3JpdGUgYW55IGNvbnRlbnRzIGF0IGFuZCBhZnRlciB0aGVcclxuICAgICAgICBzcGVjaWZpZWQgb2Zmc2V0IHVwIHRvIHRoZSBsZW5ndGggb2YgdGhpcyBCeXRlQnVmZmVyJ3MgZGF0YS5cclxuICAgICAqIEBwYXJhbSB7IUJ5dGVCdWZmZXJ9IHRhcmdldCBUYXJnZXQgQnl0ZUJ1ZmZlclxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIGFwcGVuZCB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYnkgdGhlIG51bWJlciBvZiBieXRlc1xyXG4gICAgICogIHJlYWQgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICogQHNlZSBCeXRlQnVmZmVyI2FwcGVuZFxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLmFwcGVuZFRvID0gZnVuY3Rpb24odGFyZ2V0LCBvZmZzZXQpIHtcclxuICAgICAgICB0YXJnZXQuYXBwZW5kKHRoaXMsIG9mZnNldCk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRW5hYmxlcyBvciBkaXNhYmxlcyBhc3NlcnRpb25zIG9mIGFyZ3VtZW50IHR5cGVzIGFuZCBvZmZzZXRzLiBBc3NlcnRpb25zIGFyZSBlbmFibGVkIGJ5IGRlZmF1bHQgYnV0IHlvdSBjYW4gb3B0IHRvXHJcbiAgICAgKiAgZGlzYWJsZSB0aGVtIGlmIHlvdXIgY29kZSBhbHJlYWR5IG1ha2VzIHN1cmUgdGhhdCBldmVyeXRoaW5nIGlzIHZhbGlkLlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBhc3NlcnQgYHRydWVgIHRvIGVuYWJsZSBhc3NlcnRpb25zLCBvdGhlcndpc2UgYGZhbHNlYFxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUuYXNzZXJ0ID0gZnVuY3Rpb24oYXNzZXJ0KSB7XHJcbiAgICAgICAgdGhpcy5ub0Fzc2VydCA9ICFhc3NlcnQ7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgY2FwYWNpdHkgb2YgdGhpcyBCeXRlQnVmZmVyJ3MgYmFja2luZyBidWZmZXIuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBDYXBhY2l0eSBvZiB0aGUgYmFja2luZyBidWZmZXJcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5jYXBhY2l0eSA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xyXG4gICAgfTtcclxuICAgIC8qKlxyXG4gICAgICogQ2xlYXJzIHRoaXMgQnl0ZUJ1ZmZlcidzIG9mZnNldHMgYnkgc2V0dGluZyB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IHRvIGAwYCBhbmQge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9IHRvIHRoZVxyXG4gICAgICogIGJhY2tpbmcgYnVmZmVyJ3MgY2FwYWNpdHkuIERpc2NhcmRzIHtAbGluayBCeXRlQnVmZmVyI21hcmtlZE9mZnNldH0uXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5jbGVhciA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgIHRoaXMub2Zmc2V0ID0gMDtcclxuICAgICAgICB0aGlzLmxpbWl0ID0gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aDtcclxuICAgICAgICB0aGlzLm1hcmtlZE9mZnNldCA9IC0xO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYSBjbG9uZWQgaW5zdGFuY2Ugb2YgdGhpcyBCeXRlQnVmZmVyLCBwcmVzZXQgd2l0aCB0aGlzIEJ5dGVCdWZmZXIncyB2YWx1ZXMgZm9yIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0sXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIjbWFya2VkT2Zmc2V0fSBhbmQge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9LlxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gY29weSBXaGV0aGVyIHRvIGNvcHkgdGhlIGJhY2tpbmcgYnVmZmVyIG9yIHRvIHJldHVybiBhbm90aGVyIHZpZXcgb24gdGhlIHNhbWUsIGRlZmF1bHRzIHRvIGBmYWxzZWBcclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gQ2xvbmVkIGluc3RhbmNlXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUuY2xvbmUgPSBmdW5jdGlvbihjb3B5KSB7XHJcbiAgICAgICAgdmFyIGJiID0gbmV3IEJ5dGVCdWZmZXIoMCwgdGhpcy5saXR0bGVFbmRpYW4sIHRoaXMubm9Bc3NlcnQpO1xyXG4gICAgICAgIGlmIChjb3B5KSB7XHJcbiAgICAgICAgICAgIGJiLmJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcih0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcclxuICAgICAgICAgICAgYmIudmlldyA9IG5ldyBVaW50OEFycmF5KGJiLmJ1ZmZlcik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgYmIuYnVmZmVyID0gdGhpcy5idWZmZXI7XHJcbiAgICAgICAgICAgIGJiLnZpZXcgPSB0aGlzLnZpZXc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGJiLm9mZnNldCA9IHRoaXMub2Zmc2V0O1xyXG4gICAgICAgIGJiLm1hcmtlZE9mZnNldCA9IHRoaXMubWFya2VkT2Zmc2V0O1xyXG4gICAgICAgIGJiLmxpbWl0ID0gdGhpcy5saW1pdDtcclxuICAgICAgICByZXR1cm4gYmI7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29tcGFjdHMgdGhpcyBCeXRlQnVmZmVyIHRvIGJlIGJhY2tlZCBieSBhIHtAbGluayBCeXRlQnVmZmVyI2J1ZmZlcn0gb2YgaXRzIGNvbnRlbnRzJyBsZW5ndGguIENvbnRlbnRzIGFyZSB0aGUgYnl0ZXNcclxuICAgICAqICBiZXR3ZWVuIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYW5kIHtAbGluayBCeXRlQnVmZmVyI2xpbWl0fS4gV2lsbCBzZXQgYG9mZnNldCA9IDBgIGFuZCBgbGltaXQgPSBjYXBhY2l0eWAgYW5kXHJcbiAgICAgKiAgYWRhcHQge0BsaW5rIEJ5dGVCdWZmZXIjbWFya2VkT2Zmc2V0fSB0byB0aGUgc2FtZSByZWxhdGl2ZSBwb3NpdGlvbiBpZiBzZXQuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IGJlZ2luIE9mZnNldCB0byBzdGFydCBhdCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBlbmQgT2Zmc2V0IHRvIGVuZCBhdCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9XHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5jb21wYWN0ID0gZnVuY3Rpb24oYmVnaW4sIGVuZCkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgYmVnaW4gPT09ICd1bmRlZmluZWQnKSBiZWdpbiA9IHRoaXMub2Zmc2V0O1xyXG4gICAgICAgIGlmICh0eXBlb2YgZW5kID09PSAndW5kZWZpbmVkJykgZW5kID0gdGhpcy5saW1pdDtcclxuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBiZWdpbiAhPT0gJ251bWJlcicgfHwgYmVnaW4gJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgYmVnaW46IE5vdCBhbiBpbnRlZ2VyXCIpO1xuICAgICAgICAgICAgYmVnaW4gPj4+PSAwO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBlbmQgIT09ICdudW1iZXInIHx8IGVuZCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBlbmQ6IE5vdCBhbiBpbnRlZ2VyXCIpO1xuICAgICAgICAgICAgZW5kID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChiZWdpbiA8IDAgfHwgYmVnaW4gPiBlbmQgfHwgZW5kID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCByYW5nZTogMCA8PSBcIitiZWdpbitcIiA8PSBcIitlbmQrXCIgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICBpZiAoYmVnaW4gPT09IDAgJiYgZW5kID09PSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxyXG4gICAgICAgICAgICByZXR1cm4gdGhpczsgLy8gQWxyZWFkeSBjb21wYWN0ZWRcclxuICAgICAgICB2YXIgbGVuID0gZW5kIC0gYmVnaW47XHJcbiAgICAgICAgaWYgKGxlbiA9PT0gMCkge1xyXG4gICAgICAgICAgICB0aGlzLmJ1ZmZlciA9IEVNUFRZX0JVRkZFUjtcclxuICAgICAgICAgICAgdGhpcy52aWV3ID0gbnVsbDtcclxuICAgICAgICAgICAgaWYgKHRoaXMubWFya2VkT2Zmc2V0ID49IDApIHRoaXMubWFya2VkT2Zmc2V0IC09IGJlZ2luO1xyXG4gICAgICAgICAgICB0aGlzLm9mZnNldCA9IDA7XHJcbiAgICAgICAgICAgIHRoaXMubGltaXQgPSAwO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcclxuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcihsZW4pO1xyXG4gICAgICAgIHZhciB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKTtcclxuICAgICAgICB2aWV3LnNldCh0aGlzLnZpZXcuc3ViYXJyYXkoYmVnaW4sIGVuZCkpO1xyXG4gICAgICAgIHRoaXMuYnVmZmVyID0gYnVmZmVyO1xyXG4gICAgICAgIHRoaXMudmlldyA9IHZpZXc7XHJcbiAgICAgICAgaWYgKHRoaXMubWFya2VkT2Zmc2V0ID49IDApIHRoaXMubWFya2VkT2Zmc2V0IC09IGJlZ2luO1xyXG4gICAgICAgIHRoaXMub2Zmc2V0ID0gMDtcclxuICAgICAgICB0aGlzLmxpbWl0ID0gbGVuO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYSBjb3B5IG9mIHRoaXMgQnl0ZUJ1ZmZlcidzIGNvbnRlbnRzLiBDb250ZW50cyBhcmUgdGhlIGJ5dGVzIGJldHdlZW4ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBhbmRcclxuICAgICAqICB7QGxpbmsgQnl0ZUJ1ZmZlciNsaW1pdH0uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IGJlZ2luIEJlZ2luIG9mZnNldCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fS5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gZW5kIEVuZCBvZmZzZXQsIGRlZmF1bHRzIHRvIHtAbGluayBCeXRlQnVmZmVyI2xpbWl0fS5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gQ29weVxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLmNvcHkgPSBmdW5jdGlvbihiZWdpbiwgZW5kKSB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBiZWdpbiA9PT0gJ3VuZGVmaW5lZCcpIGJlZ2luID0gdGhpcy5vZmZzZXQ7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBlbmQgPT09ICd1bmRlZmluZWQnKSBlbmQgPSB0aGlzLmxpbWl0O1xyXG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIGJlZ2luICE9PSAnbnVtYmVyJyB8fCBiZWdpbiAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBiZWdpbjogTm90IGFuIGludGVnZXJcIik7XG4gICAgICAgICAgICBiZWdpbiA+Pj49IDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVuZCAhPT0gJ251bWJlcicgfHwgZW5kICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIGVuZDogTm90IGFuIGludGVnZXJcIik7XG4gICAgICAgICAgICBlbmQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKGJlZ2luIDwgMCB8fCBiZWdpbiA+IGVuZCB8fCBlbmQgPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIHJhbmdlOiAwIDw9IFwiK2JlZ2luK1wiIDw9IFwiK2VuZCtcIiA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChiZWdpbiA9PT0gZW5kKVxyXG4gICAgICAgICAgICByZXR1cm4gbmV3IEJ5dGVCdWZmZXIoMCwgdGhpcy5saXR0bGVFbmRpYW4sIHRoaXMubm9Bc3NlcnQpO1xyXG4gICAgICAgIHZhciBjYXBhY2l0eSA9IGVuZCAtIGJlZ2luLFxyXG4gICAgICAgICAgICBiYiA9IG5ldyBCeXRlQnVmZmVyKGNhcGFjaXR5LCB0aGlzLmxpdHRsZUVuZGlhbiwgdGhpcy5ub0Fzc2VydCk7XHJcbiAgICAgICAgYmIub2Zmc2V0ID0gMDtcclxuICAgICAgICBiYi5saW1pdCA9IGNhcGFjaXR5O1xyXG4gICAgICAgIGlmIChiYi5tYXJrZWRPZmZzZXQgPj0gMCkgYmIubWFya2VkT2Zmc2V0IC09IGJlZ2luO1xyXG4gICAgICAgIHRoaXMuY29weVRvKGJiLCAwLCBiZWdpbiwgZW5kKTtcclxuICAgICAgICByZXR1cm4gYmI7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29waWVzIHRoaXMgQnl0ZUJ1ZmZlcidzIGNvbnRlbnRzIHRvIGFub3RoZXIgQnl0ZUJ1ZmZlci4gQ29udGVudHMgYXJlIHRoZSBieXRlcyBiZXR3ZWVuIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYW5kXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9LlxyXG4gICAgICogQHBhcmFtIHshQnl0ZUJ1ZmZlcn0gdGFyZ2V0IFRhcmdldCBCeXRlQnVmZmVyXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IHRhcmdldE9mZnNldCBPZmZzZXQgdG8gY29weSB0by4gV2lsbCB1c2UgYW5kIGluY3JlYXNlIHRoZSB0YXJnZXQncyB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9XHJcbiAgICAgKiAgYnkgdGhlIG51bWJlciBvZiBieXRlcyBjb3BpZWQgaWYgb21pdHRlZC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gc291cmNlT2Zmc2V0IE9mZnNldCB0byBzdGFydCBjb3B5aW5nIGZyb20uIFdpbGwgdXNlIGFuZCBpbmNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IHRoZVxyXG4gICAgICogIG51bWJlciBvZiBieXRlcyBjb3BpZWQgaWYgb21pdHRlZC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gc291cmNlTGltaXQgT2Zmc2V0IHRvIGVuZCBjb3B5aW5nIGZyb20sIGRlZmF1bHRzIHRvIHtAbGluayBCeXRlQnVmZmVyI2xpbWl0fVxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUuY29weVRvID0gZnVuY3Rpb24odGFyZ2V0LCB0YXJnZXRPZmZzZXQsIHNvdXJjZU9mZnNldCwgc291cmNlTGltaXQpIHtcclxuICAgICAgICB2YXIgcmVsYXRpdmUsXHJcbiAgICAgICAgICAgIHRhcmdldFJlbGF0aXZlO1xyXG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAoIUJ5dGVCdWZmZXIuaXNCeXRlQnVmZmVyKHRhcmdldCkpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIHRhcmdldDogTm90IGEgQnl0ZUJ1ZmZlclwiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGFyZ2V0T2Zmc2V0ID0gKHRhcmdldFJlbGF0aXZlID0gdHlwZW9mIHRhcmdldE9mZnNldCA9PT0gJ3VuZGVmaW5lZCcpID8gdGFyZ2V0Lm9mZnNldCA6IHRhcmdldE9mZnNldCB8IDA7XHJcbiAgICAgICAgc291cmNlT2Zmc2V0ID0gKHJlbGF0aXZlID0gdHlwZW9mIHNvdXJjZU9mZnNldCA9PT0gJ3VuZGVmaW5lZCcpID8gdGhpcy5vZmZzZXQgOiBzb3VyY2VPZmZzZXQgfCAwO1xyXG4gICAgICAgIHNvdXJjZUxpbWl0ID0gdHlwZW9mIHNvdXJjZUxpbWl0ID09PSAndW5kZWZpbmVkJyA/IHRoaXMubGltaXQgOiBzb3VyY2VMaW1pdCB8IDA7XHJcblxyXG4gICAgICAgIGlmICh0YXJnZXRPZmZzZXQgPCAwIHx8IHRhcmdldE9mZnNldCA+IHRhcmdldC5idWZmZXIuYnl0ZUxlbmd0aClcclxuICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgdGFyZ2V0IHJhbmdlOiAwIDw9IFwiK3RhcmdldE9mZnNldCtcIiA8PSBcIit0YXJnZXQuYnVmZmVyLmJ5dGVMZW5ndGgpO1xyXG4gICAgICAgIGlmIChzb3VyY2VPZmZzZXQgPCAwIHx8IHNvdXJjZUxpbWl0ID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcclxuICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgc291cmNlIHJhbmdlOiAwIDw9IFwiK3NvdXJjZU9mZnNldCtcIiA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcclxuXHJcbiAgICAgICAgdmFyIGxlbiA9IHNvdXJjZUxpbWl0IC0gc291cmNlT2Zmc2V0O1xyXG4gICAgICAgIGlmIChsZW4gPT09IDApXHJcbiAgICAgICAgICAgIHJldHVybiB0YXJnZXQ7IC8vIE5vdGhpbmcgdG8gY29weVxyXG5cclxuICAgICAgICB0YXJnZXQuZW5zdXJlQ2FwYWNpdHkodGFyZ2V0T2Zmc2V0ICsgbGVuKTtcclxuXHJcbiAgICAgICAgdGFyZ2V0LnZpZXcuc2V0KHRoaXMudmlldy5zdWJhcnJheShzb3VyY2VPZmZzZXQsIHNvdXJjZUxpbWl0KSwgdGFyZ2V0T2Zmc2V0KTtcclxuXHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKSB0aGlzLm9mZnNldCArPSBsZW47XHJcbiAgICAgICAgaWYgKHRhcmdldFJlbGF0aXZlKSB0YXJnZXQub2Zmc2V0ICs9IGxlbjtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWFrZXMgc3VyZSB0aGF0IHRoaXMgQnl0ZUJ1ZmZlciBpcyBiYWNrZWQgYnkgYSB7QGxpbmsgQnl0ZUJ1ZmZlciNidWZmZXJ9IG9mIGF0IGxlYXN0IHRoZSBzcGVjaWZpZWQgY2FwYWNpdHkuIElmIHRoZVxyXG4gICAgICogIGN1cnJlbnQgY2FwYWNpdHkgaXMgZXhjZWVkZWQsIGl0IHdpbGwgYmUgZG91YmxlZC4gSWYgZG91YmxlIHRoZSBjdXJyZW50IGNhcGFjaXR5IGlzIGxlc3MgdGhhbiB0aGUgcmVxdWlyZWQgY2FwYWNpdHksXHJcbiAgICAgKiAgdGhlIHJlcXVpcmVkIGNhcGFjaXR5IHdpbGwgYmUgdXNlZCBpbnN0ZWFkLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGNhcGFjaXR5IFJlcXVpcmVkIGNhcGFjaXR5XHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5lbnN1cmVDYXBhY2l0eSA9IGZ1bmN0aW9uKGNhcGFjaXR5KSB7XHJcbiAgICAgICAgdmFyIGN1cnJlbnQgPSB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoO1xyXG4gICAgICAgIGlmIChjdXJyZW50IDwgY2FwYWNpdHkpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJlc2l6ZSgoY3VycmVudCAqPSAyKSA+IGNhcGFjaXR5ID8gY3VycmVudCA6IGNhcGFjaXR5KTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPdmVyd3JpdGVzIHRoaXMgQnl0ZUJ1ZmZlcidzIGNvbnRlbnRzIHdpdGggdGhlIHNwZWNpZmllZCB2YWx1ZS4gQ29udGVudHMgYXJlIHRoZSBieXRlcyBiZXR3ZWVuXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBhbmQge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9LlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSB2YWx1ZSBCeXRlIHZhbHVlIHRvIGZpbGwgd2l0aC4gSWYgZ2l2ZW4gYXMgYSBzdHJpbmcsIHRoZSBmaXJzdCBjaGFyYWN0ZXIgaXMgdXNlZC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gYmVnaW4gQmVnaW4gb2Zmc2V0LiBXaWxsIHVzZSBhbmQgaW5jcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSB0aGUgbnVtYmVyIG9mIGJ5dGVzXHJcbiAgICAgKiAgd3JpdHRlbiBpZiBvbWl0dGVkLiBkZWZhdWx0cyB0byB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9LlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBlbmQgRW5kIG9mZnNldCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9LlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKiBAZXhhbXBsZSBgc29tZUJ5dGVCdWZmZXIuY2xlYXIoKS5maWxsKDApYCBmaWxscyB0aGUgZW50aXJlIGJhY2tpbmcgYnVmZmVyIHdpdGggemVyb2VzXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUuZmlsbCA9IGZ1bmN0aW9uKHZhbHVlLCBiZWdpbiwgZW5kKSB7XHJcbiAgICAgICAgdmFyIHJlbGF0aXZlID0gdHlwZW9mIGJlZ2luID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBiZWdpbiA9IHRoaXMub2Zmc2V0O1xuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZS5sZW5ndGggPiAwKVxyXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLmNoYXJDb2RlQXQoMCk7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBiZWdpbiA9PT0gJ3VuZGVmaW5lZCcpIGJlZ2luID0gdGhpcy5vZmZzZXQ7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBlbmQgPT09ICd1bmRlZmluZWQnKSBlbmQgPSB0aGlzLmxpbWl0O1xyXG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlICE9PSAnbnVtYmVyJyB8fCB2YWx1ZSAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCB2YWx1ZTogXCIrdmFsdWUrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIHZhbHVlIHw9IDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGJlZ2luICE9PSAnbnVtYmVyJyB8fCBiZWdpbiAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBiZWdpbjogTm90IGFuIGludGVnZXJcIik7XG4gICAgICAgICAgICBiZWdpbiA+Pj49IDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVuZCAhPT0gJ251bWJlcicgfHwgZW5kICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIGVuZDogTm90IGFuIGludGVnZXJcIik7XG4gICAgICAgICAgICBlbmQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKGJlZ2luIDwgMCB8fCBiZWdpbiA+IGVuZCB8fCBlbmQgPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIHJhbmdlOiAwIDw9IFwiK2JlZ2luK1wiIDw9IFwiK2VuZCtcIiA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChiZWdpbiA+PSBlbmQpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzOyAvLyBOb3RoaW5nIHRvIGZpbGxcclxuICAgICAgICB3aGlsZSAoYmVnaW4gPCBlbmQpIHRoaXMudmlld1tiZWdpbisrXSA9IHZhbHVlO1xyXG4gICAgICAgIGlmIChyZWxhdGl2ZSkgdGhpcy5vZmZzZXQgPSBiZWdpbjtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNYWtlcyB0aGlzIEJ5dGVCdWZmZXIgcmVhZHkgZm9yIGEgbmV3IHNlcXVlbmNlIG9mIHdyaXRlIG9yIHJlbGF0aXZlIHJlYWQgb3BlcmF0aW9ucy4gU2V0cyBgbGltaXQgPSBvZmZzZXRgIGFuZFxyXG4gICAgICogIGBvZmZzZXQgPSAwYC4gTWFrZSBzdXJlIGFsd2F5cyB0byBmbGlwIGEgQnl0ZUJ1ZmZlciB3aGVuIGFsbCByZWxhdGl2ZSByZWFkIG9yIHdyaXRlIG9wZXJhdGlvbnMgYXJlIGNvbXBsZXRlLlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUuZmxpcCA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgIHRoaXMubGltaXQgPSB0aGlzLm9mZnNldDtcclxuICAgICAgICB0aGlzLm9mZnNldCA9IDA7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG4gICAgLyoqXHJcbiAgICAgKiBNYXJrcyBhbiBvZmZzZXQgb24gdGhpcyBCeXRlQnVmZmVyIHRvIGJlIHVzZWQgbGF0ZXIuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IG9mZnNldCBPZmZzZXQgdG8gbWFyay4gRGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fS5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQHRocm93cyB7VHlwZUVycm9yfSBJZiBgb2Zmc2V0YCBpcyBub3QgYSB2YWxpZCBudW1iZXJcclxuICAgICAqIEB0aHJvd3Mge1JhbmdlRXJyb3J9IElmIGBvZmZzZXRgIGlzIG91dCBvZiBib3VuZHNcclxuICAgICAqIEBzZWUgQnl0ZUJ1ZmZlciNyZXNldFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLm1hcmsgPSBmdW5jdGlvbihvZmZzZXQpIHtcclxuICAgICAgICBvZmZzZXQgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJyA/IHRoaXMub2Zmc2V0IDogb2Zmc2V0O1xyXG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIG9mZnNldCAhPT0gJ251bWJlcicgfHwgb2Zmc2V0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIG9mZnNldDogXCIrb2Zmc2V0K1wiIChub3QgYW4gaW50ZWdlcilcIik7XG4gICAgICAgICAgICBvZmZzZXQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKG9mZnNldCA8IDAgfHwgb2Zmc2V0ICsgMCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiAwIDw9IFwiK29mZnNldCtcIiAoK1wiKzArXCIpIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5tYXJrZWRPZmZzZXQgPSBvZmZzZXQ7XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG4gICAgLyoqXHJcbiAgICAgKiBTZXRzIHRoZSBieXRlIG9yZGVyLlxyXG4gICAgICogQHBhcmFtIHtib29sZWFufSBsaXR0bGVFbmRpYW4gYHRydWVgIGZvciBsaXR0bGUgZW5kaWFuIGJ5dGUgb3JkZXIsIGBmYWxzZWAgZm9yIGJpZyBlbmRpYW5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLm9yZGVyID0gZnVuY3Rpb24obGl0dGxlRW5kaWFuKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbGl0dGxlRW5kaWFuICE9PSAnYm9vbGVhbicpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIGxpdHRsZUVuZGlhbjogTm90IGEgYm9vbGVhblwiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5saXR0bGVFbmRpYW4gPSAhIWxpdHRsZUVuZGlhbjtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTd2l0Y2hlcyAodG8pIGxpdHRsZSBlbmRpYW4gYnl0ZSBvcmRlci5cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IGxpdHRsZUVuZGlhbiBEZWZhdWx0cyB0byBgdHJ1ZWAsIG90aGVyd2lzZSB1c2VzIGJpZyBlbmRpYW5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLkxFID0gZnVuY3Rpb24obGl0dGxlRW5kaWFuKSB7XHJcbiAgICAgICAgdGhpcy5saXR0bGVFbmRpYW4gPSB0eXBlb2YgbGl0dGxlRW5kaWFuICE9PSAndW5kZWZpbmVkJyA/ICEhbGl0dGxlRW5kaWFuIDogdHJ1ZTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTd2l0Y2hlcyAodG8pIGJpZyBlbmRpYW4gYnl0ZSBvcmRlci5cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IGJpZ0VuZGlhbiBEZWZhdWx0cyB0byBgdHJ1ZWAsIG90aGVyd2lzZSB1c2VzIGxpdHRsZSBlbmRpYW5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLkJFID0gZnVuY3Rpb24oYmlnRW5kaWFuKSB7XHJcbiAgICAgICAgdGhpcy5saXR0bGVFbmRpYW4gPSB0eXBlb2YgYmlnRW5kaWFuICE9PSAndW5kZWZpbmVkJyA/ICFiaWdFbmRpYW4gOiBmYWxzZTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcbiAgICAvKipcclxuICAgICAqIFByZXBlbmRzIHNvbWUgZGF0YSB0byB0aGlzIEJ5dGVCdWZmZXIuIFRoaXMgd2lsbCBvdmVyd3JpdGUgYW55IGNvbnRlbnRzIGJlZm9yZSB0aGUgc3BlY2lmaWVkIG9mZnNldCB1cCB0byB0aGVcclxuICAgICAqICBwcmVwZW5kZWQgZGF0YSdzIGxlbmd0aC4gSWYgdGhlcmUgaXMgbm90IGVub3VnaCBzcGFjZSBhdmFpbGFibGUgYmVmb3JlIHRoZSBzcGVjaWZpZWQgYG9mZnNldGAsIHRoZSBiYWNraW5nIGJ1ZmZlclxyXG4gICAgICogIHdpbGwgYmUgcmVzaXplZCBhbmQgaXRzIGNvbnRlbnRzIG1vdmVkIGFjY29yZGluZ2x5LlxyXG4gICAgICogQHBhcmFtIHshQnl0ZUJ1ZmZlcnxzdHJpbmd8IUFycmF5QnVmZmVyfSBzb3VyY2UgRGF0YSB0byBwcmVwZW5kLiBJZiBgc291cmNlYCBpcyBhIEJ5dGVCdWZmZXIsIGl0cyBvZmZzZXQgd2lsbCBiZVxyXG4gICAgICogIG1vZGlmaWVkIGFjY29yZGluZyB0byB0aGUgcGVyZm9ybWVkIHJlYWQgb3BlcmF0aW9uLlxyXG4gICAgICogQHBhcmFtIHsoc3RyaW5nfG51bWJlcik9fSBlbmNvZGluZyBFbmNvZGluZyBpZiBgZGF0YWAgaXMgYSBzdHJpbmcgKFwiYmFzZTY0XCIsIFwiaGV4XCIsIFwiYmluYXJ5XCIsIGRlZmF1bHRzIHRvIFwidXRmOFwiKVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBvZmZzZXQgT2Zmc2V0IHRvIHByZXBlbmQgYXQuIFdpbGwgdXNlIGFuZCBkZWNyZWFzZSB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGJ5IHRoZSBudW1iZXIgb2YgYnl0ZXNcclxuICAgICAqICBwcmVwZW5kZWQgaWYgb21pdHRlZC5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICogQGV4YW1wbGUgQSByZWxhdGl2ZSBgMDA8MDEgMDIgMDM+LnByZXBlbmQoPDA0IDA1PilgIHJlc3VsdHMgaW4gYDwwNCAwNSAwMSAwMiAwMz4sIDA0IDA1fGBcclxuICAgICAqIEBleGFtcGxlIEFuIGFic29sdXRlIGAwMDwwMSAwMiAwMz4ucHJlcGVuZCg8MDQgMDU+LCAyKWAgcmVzdWx0cyBpbiBgMDQ8MDUgMDIgMDM+LCAwNCAwNXxgXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucHJlcGVuZCA9IGZ1bmN0aW9uKHNvdXJjZSwgZW5jb2RpbmcsIG9mZnNldCkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdudW1iZXInIHx8IHR5cGVvZiBlbmNvZGluZyAhPT0gJ3N0cmluZycpIHtcclxuICAgICAgICAgICAgb2Zmc2V0ID0gZW5jb2Rpbmc7XHJcbiAgICAgICAgICAgIGVuY29kaW5nID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgcmVsYXRpdmUgPSB0eXBlb2Ygb2Zmc2V0ID09PSAndW5kZWZpbmVkJztcbiAgICAgICAgaWYgKHJlbGF0aXZlKSBvZmZzZXQgPSB0aGlzLm9mZnNldDtcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2Ygb2Zmc2V0ICE9PSAnbnVtYmVyJyB8fCBvZmZzZXQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgb2Zmc2V0OiBcIitvZmZzZXQrXCIgKG5vdCBhbiBpbnRlZ2VyKVwiKTtcbiAgICAgICAgICAgIG9mZnNldCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAob2Zmc2V0IDwgMCB8fCBvZmZzZXQgKyAwID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IDAgPD0gXCIrb2Zmc2V0K1wiICgrXCIrMCtcIikgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIShzb3VyY2UgaW5zdGFuY2VvZiBCeXRlQnVmZmVyKSlcclxuICAgICAgICAgICAgc291cmNlID0gQnl0ZUJ1ZmZlci53cmFwKHNvdXJjZSwgZW5jb2RpbmcpO1xyXG4gICAgICAgIHZhciBsZW4gPSBzb3VyY2UubGltaXQgLSBzb3VyY2Uub2Zmc2V0O1xyXG4gICAgICAgIGlmIChsZW4gPD0gMCkgcmV0dXJuIHRoaXM7IC8vIE5vdGhpbmcgdG8gcHJlcGVuZFxyXG4gICAgICAgIHZhciBkaWZmID0gbGVuIC0gb2Zmc2V0O1xyXG4gICAgICAgIGlmIChkaWZmID4gMCkgeyAvLyBOb3QgZW5vdWdoIHNwYWNlIGJlZm9yZSBvZmZzZXQsIHNvIHJlc2l6ZSArIG1vdmVcclxuICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcih0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoICsgZGlmZik7XHJcbiAgICAgICAgICAgIHZhciB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKTtcclxuICAgICAgICAgICAgdmlldy5zZXQodGhpcy52aWV3LnN1YmFycmF5KG9mZnNldCwgdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCksIGxlbik7XHJcbiAgICAgICAgICAgIHRoaXMuYnVmZmVyID0gYnVmZmVyO1xyXG4gICAgICAgICAgICB0aGlzLnZpZXcgPSB2aWV3O1xyXG4gICAgICAgICAgICB0aGlzLm9mZnNldCArPSBkaWZmO1xyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXJrZWRPZmZzZXQgPj0gMCkgdGhpcy5tYXJrZWRPZmZzZXQgKz0gZGlmZjtcclxuICAgICAgICAgICAgdGhpcy5saW1pdCArPSBkaWZmO1xyXG4gICAgICAgICAgICBvZmZzZXQgKz0gZGlmZjtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB2YXIgYXJyYXlWaWV3ID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5idWZmZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLnZpZXcuc2V0KHNvdXJjZS52aWV3LnN1YmFycmF5KHNvdXJjZS5vZmZzZXQsIHNvdXJjZS5saW1pdCksIG9mZnNldCAtIGxlbik7XHJcblxyXG4gICAgICAgIHNvdXJjZS5vZmZzZXQgPSBzb3VyY2UubGltaXQ7XHJcbiAgICAgICAgaWYgKHJlbGF0aXZlKVxyXG4gICAgICAgICAgICB0aGlzLm9mZnNldCAtPSBsZW47XHJcbiAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUHJlcGVuZHMgdGhpcyBCeXRlQnVmZmVyIHRvIGFub3RoZXIgQnl0ZUJ1ZmZlci4gVGhpcyB3aWxsIG92ZXJ3cml0ZSBhbnkgY29udGVudHMgYmVmb3JlIHRoZSBzcGVjaWZpZWQgb2Zmc2V0IHVwIHRvIHRoZVxyXG4gICAgICogIHByZXBlbmRlZCBkYXRhJ3MgbGVuZ3RoLiBJZiB0aGVyZSBpcyBub3QgZW5vdWdoIHNwYWNlIGF2YWlsYWJsZSBiZWZvcmUgdGhlIHNwZWNpZmllZCBgb2Zmc2V0YCwgdGhlIGJhY2tpbmcgYnVmZmVyXHJcbiAgICAgKiAgd2lsbCBiZSByZXNpemVkIGFuZCBpdHMgY29udGVudHMgbW92ZWQgYWNjb3JkaW5nbHkuXHJcbiAgICAgKiBAcGFyYW0geyFCeXRlQnVmZmVyfSB0YXJnZXQgVGFyZ2V0IEJ5dGVCdWZmZXJcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gb2Zmc2V0IE9mZnNldCB0byBwcmVwZW5kIGF0LiBXaWxsIHVzZSBhbmQgZGVjcmVhc2Uge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBieSB0aGUgbnVtYmVyIG9mIGJ5dGVzXHJcbiAgICAgKiAgcHJlcGVuZGVkIGlmIG9taXR0ZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqIEBzZWUgQnl0ZUJ1ZmZlciNwcmVwZW5kXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUucHJlcGVuZFRvID0gZnVuY3Rpb24odGFyZ2V0LCBvZmZzZXQpIHtcclxuICAgICAgICB0YXJnZXQucHJlcGVuZCh0aGlzLCBvZmZzZXQpO1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuICAgIC8qKlxyXG4gICAgICogUHJpbnRzIGRlYnVnIGluZm9ybWF0aW9uIGFib3V0IHRoaXMgQnl0ZUJ1ZmZlcidzIGNvbnRlbnRzLlxyXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbihzdHJpbmcpPX0gb3V0IE91dHB1dCBmdW5jdGlvbiB0byBjYWxsLCBkZWZhdWx0cyB0byBjb25zb2xlLmxvZ1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnByaW50RGVidWcgPSBmdW5jdGlvbihvdXQpIHtcclxuICAgICAgICBpZiAodHlwZW9mIG91dCAhPT0gJ2Z1bmN0aW9uJykgb3V0ID0gY29uc29sZS5sb2cuYmluZChjb25zb2xlKTtcclxuICAgICAgICBvdXQoXHJcbiAgICAgICAgICAgIHRoaXMudG9TdHJpbmcoKStcIlxcblwiK1xyXG4gICAgICAgICAgICBcIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cXG5cIitcclxuICAgICAgICAgICAgdGhpcy50b0RlYnVnKC8qIGNvbHVtbnMgKi8gdHJ1ZSlcclxuICAgICAgICApO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgdGhlIG51bWJlciBvZiByZW1haW5pbmcgcmVhZGFibGUgYnl0ZXMuIENvbnRlbnRzIGFyZSB0aGUgYnl0ZXMgYmV0d2VlbiB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGFuZFxyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyI2xpbWl0fSwgc28gdGhpcyByZXR1cm5zIGBsaW1pdCAtIG9mZnNldGAuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBSZW1haW5pbmcgcmVhZGFibGUgYnl0ZXMuIE1heSBiZSBuZWdhdGl2ZSBpZiBgb2Zmc2V0ID4gbGltaXRgLlxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnJlbWFpbmluZyA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmxpbWl0IC0gdGhpcy5vZmZzZXQ7XHJcbiAgICB9O1xyXG4gICAgLyoqXHJcbiAgICAgKiBSZXNldHMgdGhpcyBCeXRlQnVmZmVyJ3Mge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fS4gSWYgYW4gb2Zmc2V0IGhhcyBiZWVuIG1hcmtlZCB0aHJvdWdoIHtAbGluayBCeXRlQnVmZmVyI21hcmt9XHJcbiAgICAgKiAgYmVmb3JlLCBgb2Zmc2V0YCB3aWxsIGJlIHNldCB0byB7QGxpbmsgQnl0ZUJ1ZmZlciNtYXJrZWRPZmZzZXR9LCB3aGljaCB3aWxsIHRoZW4gYmUgZGlzY2FyZGVkLiBJZiBubyBvZmZzZXQgaGFzIGJlZW5cclxuICAgICAqICBtYXJrZWQsIHNldHMgYG9mZnNldCA9IDBgLlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAc2VlIEJ5dGVCdWZmZXIjbWFya1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgaWYgKHRoaXMubWFya2VkT2Zmc2V0ID49IDApIHtcclxuICAgICAgICAgICAgdGhpcy5vZmZzZXQgPSB0aGlzLm1hcmtlZE9mZnNldDtcclxuICAgICAgICAgICAgdGhpcy5tYXJrZWRPZmZzZXQgPSAtMTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLm9mZnNldCA9IDA7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuICAgIC8qKlxyXG4gICAgICogUmVzaXplcyB0aGlzIEJ5dGVCdWZmZXIgdG8gYmUgYmFja2VkIGJ5IGEgYnVmZmVyIG9mIGF0IGxlYXN0IHRoZSBnaXZlbiBjYXBhY2l0eS4gV2lsbCBkbyBub3RoaW5nIGlmIGFscmVhZHkgdGhhdFxyXG4gICAgICogIGxhcmdlIG9yIGxhcmdlci5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBjYXBhY2l0eSBDYXBhY2l0eSByZXF1aXJlZFxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSB0aGlzXHJcbiAgICAgKiBAdGhyb3dzIHtUeXBlRXJyb3J9IElmIGBjYXBhY2l0eWAgaXMgbm90IGEgbnVtYmVyXHJcbiAgICAgKiBAdGhyb3dzIHtSYW5nZUVycm9yfSBJZiBgY2FwYWNpdHkgPCAwYFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnJlc2l6ZSA9IGZ1bmN0aW9uKGNhcGFjaXR5KSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgY2FwYWNpdHkgIT09ICdudW1iZXInIHx8IGNhcGFjaXR5ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIGNhcGFjaXR5OiBcIitjYXBhY2l0eStcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgY2FwYWNpdHkgfD0gMDtcbiAgICAgICAgICAgIGlmIChjYXBhY2l0eSA8IDApXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBjYXBhY2l0eTogMCA8PSBcIitjYXBhY2l0eSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICh0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoIDwgY2FwYWNpdHkpIHtcclxuICAgICAgICAgICAgdmFyIGJ1ZmZlciA9IG5ldyBBcnJheUJ1ZmZlcihjYXBhY2l0eSk7XHJcbiAgICAgICAgICAgIHZhciB2aWV3ID0gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyKTtcclxuICAgICAgICAgICAgdmlldy5zZXQodGhpcy52aWV3KTtcclxuICAgICAgICAgICAgdGhpcy5idWZmZXIgPSBidWZmZXI7XHJcbiAgICAgICAgICAgIHRoaXMudmlldyA9IHZpZXc7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuICAgIC8qKlxyXG4gICAgICogUmV2ZXJzZXMgdGhpcyBCeXRlQnVmZmVyJ3MgY29udGVudHMuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IGJlZ2luIE9mZnNldCB0byBzdGFydCBhdCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBlbmQgT2Zmc2V0IHRvIGVuZCBhdCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9XHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IHRoaXNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5yZXZlcnNlID0gZnVuY3Rpb24oYmVnaW4sIGVuZCkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgYmVnaW4gPT09ICd1bmRlZmluZWQnKSBiZWdpbiA9IHRoaXMub2Zmc2V0O1xyXG4gICAgICAgIGlmICh0eXBlb2YgZW5kID09PSAndW5kZWZpbmVkJykgZW5kID0gdGhpcy5saW1pdDtcclxuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBiZWdpbiAhPT0gJ251bWJlcicgfHwgYmVnaW4gJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgYmVnaW46IE5vdCBhbiBpbnRlZ2VyXCIpO1xuICAgICAgICAgICAgYmVnaW4gPj4+PSAwO1xuICAgICAgICAgICAgaWYgKHR5cGVvZiBlbmQgIT09ICdudW1iZXInIHx8IGVuZCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBlbmQ6IE5vdCBhbiBpbnRlZ2VyXCIpO1xuICAgICAgICAgICAgZW5kID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChiZWdpbiA8IDAgfHwgYmVnaW4gPiBlbmQgfHwgZW5kID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCByYW5nZTogMCA8PSBcIitiZWdpbitcIiA8PSBcIitlbmQrXCIgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICBpZiAoYmVnaW4gPT09IGVuZClcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7IC8vIE5vdGhpbmcgdG8gcmV2ZXJzZVxyXG4gICAgICAgIEFycmF5LnByb3RvdHlwZS5yZXZlcnNlLmNhbGwodGhpcy52aWV3LnN1YmFycmF5KGJlZ2luLCBlbmQpKTtcclxuICAgICAgICByZXR1cm4gdGhpcztcclxuICAgIH07XHJcbiAgICAvKipcclxuICAgICAqIFNraXBzIHRoZSBuZXh0IGBsZW5ndGhgIGJ5dGVzLiBUaGlzIHdpbGwganVzdCBhZHZhbmNlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gbGVuZ3RoIE51bWJlciBvZiBieXRlcyB0byBza2lwLiBNYXkgYWxzbyBiZSBuZWdhdGl2ZSB0byBtb3ZlIHRoZSBvZmZzZXQgYmFjay5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gdGhpc1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnNraXAgPSBmdW5jdGlvbihsZW5ndGgpIHtcclxuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBsZW5ndGggIT09ICdudW1iZXInIHx8IGxlbmd0aCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBsZW5ndGg6IFwiK2xlbmd0aCtcIiAobm90IGFuIGludGVnZXIpXCIpO1xuICAgICAgICAgICAgbGVuZ3RoIHw9IDA7XG4gICAgICAgIH1cclxuICAgICAgICB2YXIgb2Zmc2V0ID0gdGhpcy5vZmZzZXQgKyBsZW5ndGg7XHJcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCBsZW5ndGg6IDAgPD0gXCIrdGhpcy5vZmZzZXQrXCIgKyBcIitsZW5ndGgrXCIgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMub2Zmc2V0ID0gb2Zmc2V0O1xyXG4gICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFNsaWNlcyB0aGlzIEJ5dGVCdWZmZXIgYnkgY3JlYXRpbmcgYSBjbG9uZWQgaW5zdGFuY2Ugd2l0aCBgb2Zmc2V0ID0gYmVnaW5gIGFuZCBgbGltaXQgPSBlbmRgLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBiZWdpbiBCZWdpbiBvZmZzZXQsIGRlZmF1bHRzIHRvIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IGVuZCBFbmQgb2Zmc2V0LCBkZWZhdWx0cyB0byB7QGxpbmsgQnl0ZUJ1ZmZlciNsaW1pdH0uXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IENsb25lIG9mIHRoaXMgQnl0ZUJ1ZmZlciB3aXRoIHNsaWNpbmcgYXBwbGllZCwgYmFja2VkIGJ5IHRoZSBzYW1lIHtAbGluayBCeXRlQnVmZmVyI2J1ZmZlcn1cclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS5zbGljZSA9IGZ1bmN0aW9uKGJlZ2luLCBlbmQpIHtcclxuICAgICAgICBpZiAodHlwZW9mIGJlZ2luID09PSAndW5kZWZpbmVkJykgYmVnaW4gPSB0aGlzLm9mZnNldDtcclxuICAgICAgICBpZiAodHlwZW9mIGVuZCA9PT0gJ3VuZGVmaW5lZCcpIGVuZCA9IHRoaXMubGltaXQ7XHJcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgYmVnaW4gIT09ICdudW1iZXInIHx8IGJlZ2luICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIGJlZ2luOiBOb3QgYW4gaW50ZWdlclwiKTtcbiAgICAgICAgICAgIGJlZ2luID4+Pj0gMDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZW5kICE9PSAnbnVtYmVyJyB8fCBlbmQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgZW5kOiBOb3QgYW4gaW50ZWdlclwiKTtcbiAgICAgICAgICAgIGVuZCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAoYmVnaW4gPCAwIHx8IGJlZ2luID4gZW5kIHx8IGVuZCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgcmFuZ2U6IDAgPD0gXCIrYmVnaW4rXCIgPD0gXCIrZW5kK1wiIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIGJiID0gdGhpcy5jbG9uZSgpO1xyXG4gICAgICAgIGJiLm9mZnNldCA9IGJlZ2luO1xyXG4gICAgICAgIGJiLmxpbWl0ID0gZW5kO1xyXG4gICAgICAgIHJldHVybiBiYjtcclxuICAgIH07XHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgYSBjb3B5IG9mIHRoZSBiYWNraW5nIGJ1ZmZlciB0aGF0IGNvbnRhaW5zIHRoaXMgQnl0ZUJ1ZmZlcidzIGNvbnRlbnRzLiBDb250ZW50cyBhcmUgdGhlIGJ5dGVzIGJldHdlZW5cclxuICAgICAqICB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9IGFuZCB7QGxpbmsgQnl0ZUJ1ZmZlciNsaW1pdH0uXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBmb3JjZUNvcHkgSWYgYHRydWVgIHJldHVybnMgYSBjb3B5LCBvdGhlcndpc2UgcmV0dXJucyBhIHZpZXcgcmVmZXJlbmNpbmcgdGhlIHNhbWUgbWVtb3J5IGlmXHJcbiAgICAgKiAgcG9zc2libGUuIERlZmF1bHRzIHRvIGBmYWxzZWBcclxuICAgICAqIEByZXR1cm5zIHshQXJyYXlCdWZmZXJ9IENvbnRlbnRzIGFzIGFuIEFycmF5QnVmZmVyXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXJQcm90b3R5cGUudG9CdWZmZXIgPSBmdW5jdGlvbihmb3JjZUNvcHkpIHtcclxuICAgICAgICB2YXIgb2Zmc2V0ID0gdGhpcy5vZmZzZXQsXHJcbiAgICAgICAgICAgIGxpbWl0ID0gdGhpcy5saW1pdDtcclxuICAgICAgICBpZiAoIXRoaXMubm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBvZmZzZXQgIT09ICdudW1iZXInIHx8IG9mZnNldCAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBvZmZzZXQ6IE5vdCBhbiBpbnRlZ2VyXCIpO1xuICAgICAgICAgICAgb2Zmc2V0ID4+Pj0gMDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbGltaXQgIT09ICdudW1iZXInIHx8IGxpbWl0ICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIGxpbWl0OiBOb3QgYW4gaW50ZWdlclwiKTtcbiAgICAgICAgICAgIGxpbWl0ID4+Pj0gMDtcbiAgICAgICAgICAgIGlmIChvZmZzZXQgPCAwIHx8IG9mZnNldCA+IGxpbWl0IHx8IGxpbWl0ID4gdGhpcy5idWZmZXIuYnl0ZUxlbmd0aClcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCByYW5nZTogMCA8PSBcIitvZmZzZXQrXCIgPD0gXCIrbGltaXQrXCIgPD0gXCIrdGhpcy5idWZmZXIuYnl0ZUxlbmd0aCk7XG4gICAgICAgIH1cclxuICAgICAgICAvLyBOT1RFOiBJdCdzIG5vdCBwb3NzaWJsZSB0byBoYXZlIGFub3RoZXIgQXJyYXlCdWZmZXIgcmVmZXJlbmNlIHRoZSBzYW1lIG1lbW9yeSBhcyB0aGUgYmFja2luZyBidWZmZXIuIFRoaXMgaXNcclxuICAgICAgICAvLyBwb3NzaWJsZSB3aXRoIFVpbnQ4QXJyYXkjc3ViYXJyYXkgb25seSwgYnV0IHdlIGhhdmUgdG8gcmV0dXJuIGFuIEFycmF5QnVmZmVyIGJ5IGNvbnRyYWN0LiBTbzpcclxuICAgICAgICBpZiAoIWZvcmNlQ29weSAmJiBvZmZzZXQgPT09IDAgJiYgbGltaXQgPT09IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmJ1ZmZlcjtcclxuICAgICAgICBpZiAob2Zmc2V0ID09PSBsaW1pdClcclxuICAgICAgICAgICAgcmV0dXJuIEVNUFRZX0JVRkZFUjtcclxuICAgICAgICB2YXIgYnVmZmVyID0gbmV3IEFycmF5QnVmZmVyKGxpbWl0IC0gb2Zmc2V0KTtcclxuICAgICAgICBuZXcgVWludDhBcnJheShidWZmZXIpLnNldChuZXcgVWludDhBcnJheSh0aGlzLmJ1ZmZlcikuc3ViYXJyYXkob2Zmc2V0LCBsaW1pdCksIDApO1xyXG4gICAgICAgIHJldHVybiBidWZmZXI7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyBhIHJhdyBidWZmZXIgY29tcGFjdGVkIHRvIGNvbnRhaW4gdGhpcyBCeXRlQnVmZmVyJ3MgY29udGVudHMuIENvbnRlbnRzIGFyZSB0aGUgYnl0ZXMgYmV0d2VlblxyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyI29mZnNldH0gYW5kIHtAbGluayBCeXRlQnVmZmVyI2xpbWl0fS4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgQnl0ZUJ1ZmZlciN0b0J1ZmZlcn0uXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IGZvcmNlQ29weSBJZiBgdHJ1ZWAgcmV0dXJucyBhIGNvcHksIG90aGVyd2lzZSByZXR1cm5zIGEgdmlldyByZWZlcmVuY2luZyB0aGUgc2FtZSBtZW1vcnkuXHJcbiAgICAgKiAgRGVmYXVsdHMgdG8gYGZhbHNlYFxyXG4gICAgICogQHJldHVybnMgeyFBcnJheUJ1ZmZlcn0gQ29udGVudHMgYXMgYW4gQXJyYXlCdWZmZXJcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS50b0FycmF5QnVmZmVyID0gQnl0ZUJ1ZmZlclByb3RvdHlwZS50b0J1ZmZlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnZlcnRzIHRoZSBCeXRlQnVmZmVyJ3MgY29udGVudHMgdG8gYSBzdHJpbmcuXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZz19IGVuY29kaW5nIE91dHB1dCBlbmNvZGluZy4gUmV0dXJucyBhbiBpbmZvcm1hdGl2ZSBzdHJpbmcgcmVwcmVzZW50YXRpb24gaWYgb21pdHRlZCBidXQgYWxzbyBhbGxvd3NcclxuICAgICAqICBkaXJlY3QgY29udmVyc2lvbiB0byBcInV0ZjhcIiwgXCJoZXhcIiwgXCJiYXNlNjRcIiBhbmQgXCJiaW5hcnlcIiBlbmNvZGluZy4gXCJkZWJ1Z1wiIHJldHVybnMgYSBoZXggcmVwcmVzZW50YXRpb24gd2l0aFxyXG4gICAgICogIGhpZ2hsaWdodGVkIG9mZnNldHMuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IGJlZ2luIE9mZnNldCB0byBiZWdpbiBhdCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fVxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBlbmQgT2Zmc2V0IHRvIGVuZCBhdCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9XHJcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfSBTdHJpbmcgcmVwcmVzZW50YXRpb25cclxuICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiBgZW5jb2RpbmdgIGlzIGludmFsaWRcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uKGVuY29kaW5nLCBiZWdpbiwgZW5kKSB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBlbmNvZGluZyA9PT0gJ3VuZGVmaW5lZCcpXHJcbiAgICAgICAgICAgIHJldHVybiBcIkJ5dGVCdWZmZXJBQihvZmZzZXQ9XCIrdGhpcy5vZmZzZXQrXCIsbWFya2VkT2Zmc2V0PVwiK3RoaXMubWFya2VkT2Zmc2V0K1wiLGxpbWl0PVwiK3RoaXMubGltaXQrXCIsY2FwYWNpdHk9XCIrdGhpcy5jYXBhY2l0eSgpK1wiKVwiO1xyXG4gICAgICAgIGlmICh0eXBlb2YgZW5jb2RpbmcgPT09ICdudW1iZXInKVxyXG4gICAgICAgICAgICBlbmNvZGluZyA9IFwidXRmOFwiLFxyXG4gICAgICAgICAgICBiZWdpbiA9IGVuY29kaW5nLFxyXG4gICAgICAgICAgICBlbmQgPSBiZWdpbjtcclxuICAgICAgICBzd2l0Y2ggKGVuY29kaW5nKSB7XHJcbiAgICAgICAgICAgIGNhc2UgXCJ1dGY4XCI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50b1VURjgoYmVnaW4sIGVuZCk7XHJcbiAgICAgICAgICAgIGNhc2UgXCJiYXNlNjRcIjpcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnRvQmFzZTY0KGJlZ2luLCBlbmQpO1xyXG4gICAgICAgICAgICBjYXNlIFwiaGV4XCI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy50b0hleChiZWdpbiwgZW5kKTtcclxuICAgICAgICAgICAgY2FzZSBcImJpbmFyeVwiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9CaW5hcnkoYmVnaW4sIGVuZCk7XHJcbiAgICAgICAgICAgIGNhc2UgXCJkZWJ1Z1wiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9EZWJ1ZygpO1xyXG4gICAgICAgICAgICBjYXNlIFwiY29sdW1uc1wiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudG9Db2x1bW5zKCk7XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcihcIlVuc3VwcG9ydGVkIGVuY29kaW5nOiBcIitlbmNvZGluZyk7XHJcbiAgICAgICAgfVxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBseGl2LWVtYmVkZGFibGVcclxuXHJcbiAgICAvKipcclxuICAgICAqIGx4aXYtZW1iZWRkYWJsZSAoYykgMjAxNCBEYW5pZWwgV2lydHogPGRjb2RlQGRjb2RlLmlvPlxyXG4gICAgICogUmVsZWFzZWQgdW5kZXIgdGhlIEFwYWNoZSBMaWNlbnNlLCBWZXJzaW9uIDIuMFxyXG4gICAgICogc2VlOiBodHRwczovL2dpdGh1Yi5jb20vZGNvZGVJTy9seGl2IGZvciBkZXRhaWxzXHJcbiAgICAgKi9cclxuICAgIHZhciBseGl2ID0gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgXCJ1c2Ugc3RyaWN0XCI7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIGx4aXYgbmFtZXNwYWNlLlxyXG4gICAgICAgICAqIEB0eXBlIHshT2JqZWN0LjxzdHJpbmcsKj59XHJcbiAgICAgICAgICogQGV4cG9ydHMgbHhpdlxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHZhciBseGl2ID0ge307XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIENoYXJhY3RlciBjb2RlcyBmb3Igb3V0cHV0LlxyXG4gICAgICAgICAqIEB0eXBlIHshQXJyYXkuPG51bWJlcj59XHJcbiAgICAgICAgICogQGlubmVyXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdmFyIGFvdXQgPSBbXHJcbiAgICAgICAgICAgIDY1LCA2NiwgNjcsIDY4LCA2OSwgNzAsIDcxLCA3MiwgNzMsIDc0LCA3NSwgNzYsIDc3LCA3OCwgNzksIDgwLFxyXG4gICAgICAgICAgICA4MSwgODIsIDgzLCA4NCwgODUsIDg2LCA4NywgODgsIDg5LCA5MCwgOTcsIDk4LCA5OSwgMTAwLCAxMDEsIDEwMixcclxuICAgICAgICAgICAgMTAzLCAxMDQsIDEwNSwgMTA2LCAxMDcsIDEwOCwgMTA5LCAxMTAsIDExMSwgMTEyLCAxMTMsIDExNCwgMTE1LCAxMTYsIDExNywgMTE4LFxyXG4gICAgICAgICAgICAxMTksIDEyMCwgMTIxLCAxMjIsIDQ4LCA0OSwgNTAsIDUxLCA1MiwgNTMsIDU0LCA1NSwgNTYsIDU3LCA0MywgNDdcclxuICAgICAgICBdO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBDaGFyYWN0ZXIgY29kZXMgZm9yIGlucHV0LlxyXG4gICAgICAgICAqIEB0eXBlIHshQXJyYXkuPG51bWJlcj59XHJcbiAgICAgICAgICogQGlubmVyXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdmFyIGFpbiA9IFtdO1xyXG4gICAgICAgIGZvciAodmFyIGk9MCwgaz1hb3V0Lmxlbmd0aDsgaTxrOyArK2kpXHJcbiAgICAgICAgICAgIGFpblthb3V0W2ldXSA9IGk7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIEVuY29kZXMgYnl0ZXMgdG8gYmFzZTY0IGNoYXIgY29kZXMuXHJcbiAgICAgICAgICogQHBhcmFtIHshZnVuY3Rpb24oKTpudW1iZXJ8bnVsbH0gc3JjIEJ5dGVzIHNvdXJjZSBhcyBhIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgbmV4dCBieXRlIHJlc3BlY3RpdmVseSBgbnVsbGAgaWZcclxuICAgICAgICAgKiAgdGhlcmUgYXJlIG5vIG1vcmUgYnl0ZXMgbGVmdC5cclxuICAgICAgICAgKiBAcGFyYW0geyFmdW5jdGlvbihudW1iZXIpfSBkc3QgQ2hhcmFjdGVycyBkZXN0aW5hdGlvbiBhcyBhIGZ1bmN0aW9uIHN1Y2Nlc3NpdmVseSBjYWxsZWQgd2l0aCBlYWNoIGVuY29kZWQgY2hhclxyXG4gICAgICAgICAqICBjb2RlLlxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIGx4aXYuZW5jb2RlID0gZnVuY3Rpb24oc3JjLCBkc3QpIHtcclxuICAgICAgICAgICAgdmFyIGIsIHQ7XHJcbiAgICAgICAgICAgIHdoaWxlICgoYiA9IHNyYygpKSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgZHN0KGFvdXRbKGI+PjIpJjB4M2ZdKTtcclxuICAgICAgICAgICAgICAgIHQgPSAoYiYweDMpPDw0O1xyXG4gICAgICAgICAgICAgICAgaWYgKChiID0gc3JjKCkpICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdCB8PSAoYj4+NCkmMHhmO1xyXG4gICAgICAgICAgICAgICAgICAgIGRzdChhb3V0Wyh0fCgoYj4+NCkmMHhmKSkmMHgzZl0pO1xyXG4gICAgICAgICAgICAgICAgICAgIHQgPSAoYiYweGYpPDwyO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICgoYiA9IHNyYygpKSAhPT0gbnVsbClcclxuICAgICAgICAgICAgICAgICAgICAgICAgZHN0KGFvdXRbKHR8KChiPj42KSYweDMpKSYweDNmXSksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRzdChhb3V0W2ImMHgzZl0pO1xyXG4gICAgICAgICAgICAgICAgICAgIGVsc2VcclxuICAgICAgICAgICAgICAgICAgICAgICAgZHN0KGFvdXRbdCYweDNmXSksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRzdCg2MSk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2VcclxuICAgICAgICAgICAgICAgICAgICBkc3QoYW91dFt0JjB4M2ZdKSxcclxuICAgICAgICAgICAgICAgICAgICBkc3QoNjEpLFxyXG4gICAgICAgICAgICAgICAgICAgIGRzdCg2MSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBEZWNvZGVzIGJhc2U2NCBjaGFyIGNvZGVzIHRvIGJ5dGVzLlxyXG4gICAgICAgICAqIEBwYXJhbSB7IWZ1bmN0aW9uKCk6bnVtYmVyfG51bGx9IHNyYyBDaGFyYWN0ZXJzIHNvdXJjZSBhcyBhIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgbmV4dCBjaGFyIGNvZGUgcmVzcGVjdGl2ZWx5XHJcbiAgICAgICAgICogIGBudWxsYCBpZiB0aGVyZSBhcmUgbm8gbW9yZSBjaGFyYWN0ZXJzIGxlZnQuXHJcbiAgICAgICAgICogQHBhcmFtIHshZnVuY3Rpb24obnVtYmVyKX0gZHN0IEJ5dGVzIGRlc3RpbmF0aW9uIGFzIGEgZnVuY3Rpb24gc3VjY2Vzc2l2ZWx5IGNhbGxlZCB3aXRoIHRoZSBuZXh0IGJ5dGUuXHJcbiAgICAgICAgICogQHRocm93cyB7RXJyb3J9IElmIGEgY2hhcmFjdGVyIGNvZGUgaXMgaW52YWxpZFxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIGx4aXYuZGVjb2RlID0gZnVuY3Rpb24oc3JjLCBkc3QpIHtcclxuICAgICAgICAgICAgdmFyIGMsIHQxLCB0MjtcclxuICAgICAgICAgICAgZnVuY3Rpb24gZmFpbChjKSB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBFcnJvcihcIklsbGVnYWwgY2hhcmFjdGVyIGNvZGU6IFwiK2MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHdoaWxlICgoYyA9IHNyYygpKSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgdDEgPSBhaW5bY107XHJcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHQxID09PSAndW5kZWZpbmVkJykgZmFpbChjKTtcclxuICAgICAgICAgICAgICAgIGlmICgoYyA9IHNyYygpKSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHQyID0gYWluW2NdO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdDIgPT09ICd1bmRlZmluZWQnKSBmYWlsKGMpO1xyXG4gICAgICAgICAgICAgICAgICAgIGRzdCgodDE8PDIpPj4+MHwodDImMHgzMCk+PjQpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICgoYyA9IHNyYygpKSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0MSA9IGFpbltjXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0MSA9PT0gJ3VuZGVmaW5lZCcpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYyA9PT0gNjEpIGJyZWFrOyBlbHNlIGZhaWwoYyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRzdCgoKHQyJjB4Zik8PDQpPj4+MHwodDEmMHgzYyk+PjIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKGMgPSBzcmMoKSkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHQyID0gYWluW2NdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0MiA9PT0gJ3VuZGVmaW5lZCcpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGMgPT09IDYxKSBicmVhazsgZWxzZSBmYWlsKGMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZHN0KCgodDEmMHgzKTw8Nik+Pj4wfHQyKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFRlc3RzIGlmIGEgc3RyaW5nIGlzIHZhbGlkIGJhc2U2NC5cclxuICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFN0cmluZyB0byB0ZXN0XHJcbiAgICAgICAgICogQHJldHVybnMge2Jvb2xlYW59IGB0cnVlYCBpZiB2YWxpZCwgb3RoZXJ3aXNlIGBmYWxzZWBcclxuICAgICAgICAgKi9cclxuICAgICAgICBseGl2LnRlc3QgPSBmdW5jdGlvbihzdHIpIHtcclxuICAgICAgICAgICAgcmV0dXJuIC9eKD86W0EtWmEtejAtOSsvXXs0fSkqKD86W0EtWmEtejAtOSsvXXsyfT09fFtBLVphLXowLTkrL117M309KT8kLy50ZXN0KHN0cik7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGx4aXY7XHJcbiAgICB9KCk7XHJcblxyXG4gICAgLy8gZW5jb2RpbmdzL2Jhc2U2NFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRW5jb2RlcyB0aGlzIEJ5dGVCdWZmZXIncyBjb250ZW50cyB0byBhIGJhc2U2NCBlbmNvZGVkIHN0cmluZy5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gYmVnaW4gT2Zmc2V0IHRvIGJlZ2luIGF0LCBkZWZhdWx0cyB0byB7QGxpbmsgQnl0ZUJ1ZmZlciNvZmZzZXR9LlxyXG4gICAgICogQHBhcmFtIHtudW1iZXI9fSBlbmQgT2Zmc2V0IHRvIGVuZCBhdCwgZGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9LlxyXG4gICAgICogQHJldHVybnMge3N0cmluZ30gQmFzZTY0IGVuY29kZWQgc3RyaW5nXHJcbiAgICAgKiBAdGhyb3dzIHtSYW5nZUVycm9yfSBJZiBgYmVnaW5gIG9yIGBlbmRgIGlzIG91dCBvZiBib3VuZHNcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlclByb3RvdHlwZS50b0Jhc2U2NCA9IGZ1bmN0aW9uKGJlZ2luLCBlbmQpIHtcclxuICAgICAgICBpZiAodHlwZW9mIGJlZ2luID09PSAndW5kZWZpbmVkJylcclxuICAgICAgICAgICAgYmVnaW4gPSB0aGlzLm9mZnNldDtcclxuICAgICAgICBpZiAodHlwZW9mIGVuZCA9PT0gJ3VuZGVmaW5lZCcpXHJcbiAgICAgICAgICAgIGVuZCA9IHRoaXMubGltaXQ7XHJcbiAgICAgICAgYmVnaW4gPSBiZWdpbiB8IDA7IGVuZCA9IGVuZCB8IDA7XHJcbiAgICAgICAgaWYgKGJlZ2luIDwgMCB8fCBlbmQgPiB0aGlzLmNhcGFjaXR5IHx8IGJlZ2luID4gZW5kKVxyXG4gICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiYmVnaW4sIGVuZFwiKTtcclxuICAgICAgICB2YXIgc2Q7IGx4aXYuZW5jb2RlKGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICByZXR1cm4gYmVnaW4gPCBlbmQgPyB0aGlzLnZpZXdbYmVnaW4rK10gOiBudWxsO1xyXG4gICAgICAgIH0uYmluZCh0aGlzKSwgc2QgPSBzdHJpbmdEZXN0aW5hdGlvbigpKTtcclxuICAgICAgICByZXR1cm4gc2QoKTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWNvZGVzIGEgYmFzZTY0IGVuY29kZWQgc3RyaW5nIHRvIGEgQnl0ZUJ1ZmZlci5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgU3RyaW5nIHRvIGRlY29kZVxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gbGl0dGxlRW5kaWFuIFdoZXRoZXIgdG8gdXNlIGxpdHRsZSBvciBiaWcgZW5kaWFuIGJ5dGUgb3JkZXIuIERlZmF1bHRzIHRvXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIuREVGQVVMVF9FTkRJQU59LlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSBCeXRlQnVmZmVyXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuZnJvbUJhc2U2NCA9IGZ1bmN0aW9uKHN0ciwgbGl0dGxlRW5kaWFuKSB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJzdHJcIik7XHJcbiAgICAgICAgdmFyIGJiID0gbmV3IEJ5dGVCdWZmZXIoc3RyLmxlbmd0aC80KjMsIGxpdHRsZUVuZGlhbiksXHJcbiAgICAgICAgICAgIGkgPSAwO1xyXG4gICAgICAgIGx4aXYuZGVjb2RlKHN0cmluZ1NvdXJjZShzdHIpLCBmdW5jdGlvbihiKSB7XHJcbiAgICAgICAgICAgIGJiLnZpZXdbaSsrXSA9IGI7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgYmIubGltaXQgPSBpO1xyXG4gICAgICAgIHJldHVybiBiYjtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFbmNvZGVzIGEgYmluYXJ5IHN0cmluZyB0byBiYXNlNjQgbGlrZSBgd2luZG93LmJ0b2FgIGRvZXMuXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIEJpbmFyeSBzdHJpbmdcclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IEJhc2U2NCBlbmNvZGVkIHN0cmluZ1xyXG4gICAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93LmJ0b2FcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlci5idG9hID0gZnVuY3Rpb24oc3RyKSB7XHJcbiAgICAgICAgcmV0dXJuIEJ5dGVCdWZmZXIuZnJvbUJpbmFyeShzdHIpLnRvQmFzZTY0KCk7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVjb2RlcyBhIGJhc2U2NCBlbmNvZGVkIHN0cmluZyB0byBiaW5hcnkgbGlrZSBgd2luZG93LmF0b2JgIGRvZXMuXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gYjY0IEJhc2U2NCBlbmNvZGVkIHN0cmluZ1xyXG4gICAgICogQHJldHVybnMge3N0cmluZ30gQmluYXJ5IHN0cmluZ1xyXG4gICAgICogQHNlZSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvV2luZG93LmF0b2JcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlci5hdG9iID0gZnVuY3Rpb24oYjY0KSB7XHJcbiAgICAgICAgcmV0dXJuIEJ5dGVCdWZmZXIuZnJvbUJhc2U2NChiNjQpLnRvQmluYXJ5KCk7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIGVuY29kaW5ncy9iaW5hcnlcclxuXHJcbiAgICAvKipcclxuICAgICAqIEVuY29kZXMgdGhpcyBCeXRlQnVmZmVyIHRvIGEgYmluYXJ5IGVuY29kZWQgc3RyaW5nLCB0aGF0IGlzIHVzaW5nIG9ubHkgY2hhcmFjdGVycyAweDAwLTB4RkYgYXMgYnl0ZXMuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IGJlZ2luIE9mZnNldCB0byBiZWdpbiBhdC4gRGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fS5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gZW5kIE9mZnNldCB0byBlbmQgYXQuIERlZmF1bHRzIHRvIHtAbGluayBCeXRlQnVmZmVyI2xpbWl0fS5cclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IEJpbmFyeSBlbmNvZGVkIHN0cmluZ1xyXG4gICAgICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYG9mZnNldCA+IGxpbWl0YFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnRvQmluYXJ5ID0gZnVuY3Rpb24oYmVnaW4sIGVuZCkge1xyXG4gICAgICAgIGlmICh0eXBlb2YgYmVnaW4gPT09ICd1bmRlZmluZWQnKVxyXG4gICAgICAgICAgICBiZWdpbiA9IHRoaXMub2Zmc2V0O1xyXG4gICAgICAgIGlmICh0eXBlb2YgZW5kID09PSAndW5kZWZpbmVkJylcclxuICAgICAgICAgICAgZW5kID0gdGhpcy5saW1pdDtcclxuICAgICAgICBiZWdpbiB8PSAwOyBlbmQgfD0gMDtcclxuICAgICAgICBpZiAoYmVnaW4gPCAwIHx8IGVuZCA+IHRoaXMuY2FwYWNpdHkoKSB8fCBiZWdpbiA+IGVuZClcclxuICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcImJlZ2luLCBlbmRcIik7XHJcbiAgICAgICAgaWYgKGJlZ2luID09PSBlbmQpXHJcbiAgICAgICAgICAgIHJldHVybiBcIlwiO1xyXG4gICAgICAgIHZhciBjaGFycyA9IFtdLFxyXG4gICAgICAgICAgICBwYXJ0cyA9IFtdO1xyXG4gICAgICAgIHdoaWxlIChiZWdpbiA8IGVuZCkge1xyXG4gICAgICAgICAgICBjaGFycy5wdXNoKHRoaXMudmlld1tiZWdpbisrXSk7XHJcbiAgICAgICAgICAgIGlmIChjaGFycy5sZW5ndGggPj0gMTAyNClcclxuICAgICAgICAgICAgICAgIHBhcnRzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZS5hcHBseShTdHJpbmcsIGNoYXJzKSksXHJcbiAgICAgICAgICAgICAgICBjaGFycyA9IFtdO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcGFydHMuam9pbignJykgKyBTdHJpbmcuZnJvbUNoYXJDb2RlLmFwcGx5KFN0cmluZywgY2hhcnMpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlY29kZXMgYSBiaW5hcnkgZW5jb2RlZCBzdHJpbmcsIHRoYXQgaXMgdXNpbmcgb25seSBjaGFyYWN0ZXJzIDB4MDAtMHhGRiBhcyBieXRlcywgdG8gYSBCeXRlQnVmZmVyLlxyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciBTdHJpbmcgdG8gZGVjb2RlXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSBsaXR0bGVFbmRpYW4gV2hldGhlciB0byB1c2UgbGl0dGxlIG9yIGJpZyBlbmRpYW4gYnl0ZSBvcmRlci4gRGVmYXVsdHMgdG9cclxuICAgICAqICB7QGxpbmsgQnl0ZUJ1ZmZlci5ERUZBVUxUX0VORElBTn0uXHJcbiAgICAgKiBAcmV0dXJucyB7IUJ5dGVCdWZmZXJ9IEJ5dGVCdWZmZXJcclxuICAgICAqIEBleHBvc2VcclxuICAgICAqL1xyXG4gICAgQnl0ZUJ1ZmZlci5mcm9tQmluYXJ5ID0gZnVuY3Rpb24oc3RyLCBsaXR0bGVFbmRpYW4pIHtcclxuICAgICAgICBpZiAodHlwZW9mIHN0ciAhPT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcInN0clwiKTtcclxuICAgICAgICB2YXIgaSA9IDAsXHJcbiAgICAgICAgICAgIGsgPSBzdHIubGVuZ3RoLFxyXG4gICAgICAgICAgICBjaGFyQ29kZSxcclxuICAgICAgICAgICAgYmIgPSBuZXcgQnl0ZUJ1ZmZlcihrLCBsaXR0bGVFbmRpYW4pO1xyXG4gICAgICAgIHdoaWxlIChpPGspIHtcclxuICAgICAgICAgICAgY2hhckNvZGUgPSBzdHIuY2hhckNvZGVBdChpKTtcclxuICAgICAgICAgICAgaWYgKGNoYXJDb2RlID4gMHhmZilcclxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJpbGxlZ2FsIGNoYXIgY29kZTogXCIrY2hhckNvZGUpO1xyXG4gICAgICAgICAgICBiYi52aWV3W2krK10gPSBjaGFyQ29kZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgYmIubGltaXQgPSBrO1xyXG4gICAgICAgIHJldHVybiBiYjtcclxuICAgIH07XHJcblxyXG4gICAgLy8gZW5jb2RpbmdzL2RlYnVnXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFbmNvZGVzIHRoaXMgQnl0ZUJ1ZmZlciB0byBhIGhleCBlbmNvZGVkIHN0cmluZyB3aXRoIG1hcmtlZCBvZmZzZXRzLiBPZmZzZXQgc3ltYm9scyBhcmU6XHJcbiAgICAgKiAqIGA8YCA6IG9mZnNldCxcclxuICAgICAqICogYCdgIDogbWFya2VkT2Zmc2V0LFxyXG4gICAgICogKiBgPmAgOiBsaW1pdCxcclxuICAgICAqICogYHxgIDogb2Zmc2V0IGFuZCBsaW1pdCxcclxuICAgICAqICogYFtgIDogb2Zmc2V0IGFuZCBtYXJrZWRPZmZzZXQsXHJcbiAgICAgKiAqIGBdYCA6IG1hcmtlZE9mZnNldCBhbmQgbGltaXQsXHJcbiAgICAgKiAqIGAhYCA6IG9mZnNldCwgbWFya2VkT2Zmc2V0IGFuZCBsaW1pdFxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gY29sdW1ucyBJZiBgdHJ1ZWAgcmV0dXJucyB0d28gY29sdW1ucyBoZXggKyBhc2NpaSwgZGVmYXVsdHMgdG8gYGZhbHNlYFxyXG4gICAgICogQHJldHVybnMge3N0cmluZ3whQXJyYXkuPHN0cmluZz59IERlYnVnIHN0cmluZyBvciBhcnJheSBvZiBsaW5lcyBpZiBgYXNBcnJheSA9IHRydWVgXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKiBAZXhhbXBsZSBgPjAwJzAxIDAyPDAzYCBjb250YWlucyBmb3VyIGJ5dGVzIHdpdGggYGxpbWl0PTAsIG1hcmtlZE9mZnNldD0xLCBvZmZzZXQ9M2BcclxuICAgICAqIEBleGFtcGxlIGAwMFswMSAwMiAwMz5gIGNvbnRhaW5zIGZvdXIgYnl0ZXMgd2l0aCBgb2Zmc2V0PW1hcmtlZE9mZnNldD0xLCBsaW1pdD00YFxyXG4gICAgICogQGV4YW1wbGUgYDAwfDAxIDAyIDAzYCBjb250YWlucyBmb3VyIGJ5dGVzIHdpdGggYG9mZnNldD1saW1pdD0xLCBtYXJrZWRPZmZzZXQ9LTFgXHJcbiAgICAgKiBAZXhhbXBsZSBgfGAgY29udGFpbnMgemVybyBieXRlcyB3aXRoIGBvZmZzZXQ9bGltaXQ9MCwgbWFya2VkT2Zmc2V0PS0xYFxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnRvRGVidWcgPSBmdW5jdGlvbihjb2x1bW5zKSB7XHJcbiAgICAgICAgdmFyIGkgPSAtMSxcclxuICAgICAgICAgICAgayA9IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgsXHJcbiAgICAgICAgICAgIGIsXHJcbiAgICAgICAgICAgIGhleCA9IFwiXCIsXHJcbiAgICAgICAgICAgIGFzYyA9IFwiXCIsXHJcbiAgICAgICAgICAgIG91dCA9IFwiXCI7XHJcbiAgICAgICAgd2hpbGUgKGk8aykge1xyXG4gICAgICAgICAgICBpZiAoaSAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgIGIgPSB0aGlzLnZpZXdbaV07XHJcbiAgICAgICAgICAgICAgICBpZiAoYiA8IDB4MTApIGhleCArPSBcIjBcIitiLnRvU3RyaW5nKDE2KS50b1VwcGVyQ2FzZSgpO1xyXG4gICAgICAgICAgICAgICAgZWxzZSBoZXggKz0gYi50b1N0cmluZygxNikudG9VcHBlckNhc2UoKTtcclxuICAgICAgICAgICAgICAgIGlmIChjb2x1bW5zKVxyXG4gICAgICAgICAgICAgICAgICAgIGFzYyArPSBiID4gMzIgJiYgYiA8IDEyNyA/IFN0cmluZy5mcm9tQ2hhckNvZGUoYikgOiAnLic7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKytpO1xyXG4gICAgICAgICAgICBpZiAoY29sdW1ucykge1xyXG4gICAgICAgICAgICAgICAgaWYgKGkgPiAwICYmIGkgJSAxNiA9PT0gMCAmJiBpICE9PSBrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgd2hpbGUgKGhleC5sZW5ndGggPCAzKjE2KzMpIGhleCArPSBcIiBcIjtcclxuICAgICAgICAgICAgICAgICAgICBvdXQgKz0gaGV4K2FzYytcIlxcblwiO1xyXG4gICAgICAgICAgICAgICAgICAgIGhleCA9IGFzYyA9IFwiXCI7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKGkgPT09IHRoaXMub2Zmc2V0ICYmIGkgPT09IHRoaXMubGltaXQpXHJcbiAgICAgICAgICAgICAgICBoZXggKz0gaSA9PT0gdGhpcy5tYXJrZWRPZmZzZXQgPyBcIiFcIiA6IFwifFwiO1xyXG4gICAgICAgICAgICBlbHNlIGlmIChpID09PSB0aGlzLm9mZnNldClcclxuICAgICAgICAgICAgICAgIGhleCArPSBpID09PSB0aGlzLm1hcmtlZE9mZnNldCA/IFwiW1wiIDogXCI8XCI7XHJcbiAgICAgICAgICAgIGVsc2UgaWYgKGkgPT09IHRoaXMubGltaXQpXHJcbiAgICAgICAgICAgICAgICBoZXggKz0gaSA9PT0gdGhpcy5tYXJrZWRPZmZzZXQgPyBcIl1cIiA6IFwiPlwiO1xyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICBoZXggKz0gaSA9PT0gdGhpcy5tYXJrZWRPZmZzZXQgPyBcIidcIiA6IChjb2x1bW5zIHx8IChpICE9PSAwICYmIGkgIT09IGspID8gXCIgXCIgOiBcIlwiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGNvbHVtbnMgJiYgaGV4ICE9PSBcIiBcIikge1xyXG4gICAgICAgICAgICB3aGlsZSAoaGV4Lmxlbmd0aCA8IDMqMTYrMylcclxuICAgICAgICAgICAgICAgIGhleCArPSBcIiBcIjtcclxuICAgICAgICAgICAgb3V0ICs9IGhleCArIGFzYyArIFwiXFxuXCI7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBjb2x1bW5zID8gb3V0IDogaGV4O1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlY29kZXMgYSBoZXggZW5jb2RlZCBzdHJpbmcgd2l0aCBtYXJrZWQgb2Zmc2V0cyB0byBhIEJ5dGVCdWZmZXIuXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIERlYnVnIHN0cmluZyB0byBkZWNvZGUgKG5vdCBiZSBnZW5lcmF0ZWQgd2l0aCBgY29sdW1ucyA9IHRydWVgKVxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gbGl0dGxlRW5kaWFuIFdoZXRoZXIgdG8gdXNlIGxpdHRsZSBvciBiaWcgZW5kaWFuIGJ5dGUgb3JkZXIuIERlZmF1bHRzIHRvXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIuREVGQVVMVF9FTkRJQU59LlxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gbm9Bc3NlcnQgV2hldGhlciB0byBza2lwIGFzc2VydGlvbnMgb2Ygb2Zmc2V0cyBhbmQgdmFsdWVzLiBEZWZhdWx0cyB0b1xyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyLkRFRkFVTFRfTk9BU1NFUlR9LlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSBCeXRlQnVmZmVyXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKiBAc2VlIEJ5dGVCdWZmZXIjdG9EZWJ1Z1xyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLmZyb21EZWJ1ZyA9IGZ1bmN0aW9uKHN0ciwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xyXG4gICAgICAgIHZhciBrID0gc3RyLmxlbmd0aCxcclxuICAgICAgICAgICAgYmIgPSBuZXcgQnl0ZUJ1ZmZlcigoKGsrMSkvMyl8MCwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCk7XHJcbiAgICAgICAgdmFyIGkgPSAwLCBqID0gMCwgY2gsIGIsXHJcbiAgICAgICAgICAgIHJzID0gZmFsc2UsIC8vIFJlcXVpcmUgc3ltYm9sIG5leHRcclxuICAgICAgICAgICAgaG8gPSBmYWxzZSwgaG0gPSBmYWxzZSwgaGwgPSBmYWxzZSwgLy8gQWxyZWFkeSBoYXMgb2Zmc2V0IChobyksIG1hcmtlZE9mZnNldCAoaG0pLCBsaW1pdCAoaGwpP1xyXG4gICAgICAgICAgICBmYWlsID0gZmFsc2U7XHJcbiAgICAgICAgd2hpbGUgKGk8aykge1xyXG4gICAgICAgICAgICBzd2l0Y2ggKGNoID0gc3RyLmNoYXJBdChpKyspKSB7XHJcbiAgICAgICAgICAgICAgICBjYXNlICchJzpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIW5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChobyB8fCBobSB8fCBobCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBobyA9IGhtID0gaGwgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBiYi5vZmZzZXQgPSBiYi5tYXJrZWRPZmZzZXQgPSBiYi5saW1pdCA9IGo7XHJcbiAgICAgICAgICAgICAgICAgICAgcnMgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgJ3wnOlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghbm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhvIHx8IGhsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGhvID0gaGwgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBiYi5vZmZzZXQgPSBiYi5saW1pdCA9IGo7XHJcbiAgICAgICAgICAgICAgICAgICAgcnMgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgJ1snOlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghbm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhvIHx8IGhtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGhvID0gaG0gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBiYi5vZmZzZXQgPSBiYi5tYXJrZWRPZmZzZXQgPSBqO1xyXG4gICAgICAgICAgICAgICAgICAgIHJzID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlICc8JzpcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIW5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChobykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFpbCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBobyA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGJiLm9mZnNldCA9IGo7XHJcbiAgICAgICAgICAgICAgICAgICAgcnMgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgJ10nOlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghbm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhsIHx8IGhtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGhsID0gaG0gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBiYi5saW1pdCA9IGJiLm1hcmtlZE9mZnNldCA9IGo7XHJcbiAgICAgICAgICAgICAgICAgICAgcnMgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgJz4nOlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghbm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGhsID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgYmIubGltaXQgPSBqO1xyXG4gICAgICAgICAgICAgICAgICAgIHJzID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBjYXNlIFwiJ1wiOlxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghbm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGhtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBmYWlsID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGhtID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgYmIubWFya2VkT2Zmc2V0ID0gajtcclxuICAgICAgICAgICAgICAgICAgICBycyA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgY2FzZSAnICc6XHJcbiAgICAgICAgICAgICAgICAgICAgcnMgPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFub0Fzc2VydCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocnMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZhaWwgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgYiA9IHBhcnNlSW50KGNoK3N0ci5jaGFyQXQoaSsrKSwgMTYpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICghbm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzTmFOKGIpIHx8IGIgPCAwIHx8IGIgPiAyNTUpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIHN0cjogTm90IGEgZGVidWcgZW5jb2RlZCBzdHJpbmdcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGJiLnZpZXdbaisrXSA9IGI7XHJcbiAgICAgICAgICAgICAgICAgICAgcnMgPSB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmIChmYWlsKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBzdHI6IEludmFsaWQgc3ltYm9sIGF0IFwiK2kpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIW5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICghaG8gfHwgIWhsKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBzdHI6IE1pc3Npbmcgb2Zmc2V0IG9yIGxpbWl0XCIpO1xyXG4gICAgICAgICAgICBpZiAoajxiYi5idWZmZXIuYnl0ZUxlbmd0aClcclxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgc3RyOiBOb3QgYSBkZWJ1ZyBlbmNvZGVkIHN0cmluZyAoaXMgaXQgaGV4PykgXCIraitcIiA8IFwiK2spO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gYmI7XHJcbiAgICB9O1xyXG5cclxuICAgIC8vIGVuY29kaW5ncy9oZXhcclxuXHJcbiAgICAvKipcclxuICAgICAqIEVuY29kZXMgdGhpcyBCeXRlQnVmZmVyJ3MgY29udGVudHMgdG8gYSBoZXggZW5jb2RlZCBzdHJpbmcuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IGJlZ2luIE9mZnNldCB0byBiZWdpbiBhdC4gRGVmYXVsdHMgdG8ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fS5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gZW5kIE9mZnNldCB0byBlbmQgYXQuIERlZmF1bHRzIHRvIHtAbGluayBCeXRlQnVmZmVyI2xpbWl0fS5cclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IEhleCBlbmNvZGVkIHN0cmluZ1xyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnRvSGV4ID0gZnVuY3Rpb24oYmVnaW4sIGVuZCkge1xyXG4gICAgICAgIGJlZ2luID0gdHlwZW9mIGJlZ2luID09PSAndW5kZWZpbmVkJyA/IHRoaXMub2Zmc2V0IDogYmVnaW47XHJcbiAgICAgICAgZW5kID0gdHlwZW9mIGVuZCA9PT0gJ3VuZGVmaW5lZCcgPyB0aGlzLmxpbWl0IDogZW5kO1xyXG4gICAgICAgIGlmICghdGhpcy5ub0Fzc2VydCkge1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIGJlZ2luICE9PSAnbnVtYmVyJyB8fCBiZWdpbiAlIDEgIT09IDApXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBiZWdpbjogTm90IGFuIGludGVnZXJcIik7XG4gICAgICAgICAgICBiZWdpbiA+Pj49IDA7XG4gICAgICAgICAgICBpZiAodHlwZW9mIGVuZCAhPT0gJ251bWJlcicgfHwgZW5kICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIGVuZDogTm90IGFuIGludGVnZXJcIik7XG4gICAgICAgICAgICBlbmQgPj4+PSAwO1xuICAgICAgICAgICAgaWYgKGJlZ2luIDwgMCB8fCBiZWdpbiA+IGVuZCB8fCBlbmQgPiB0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKVxuICAgICAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIHJhbmdlOiAwIDw9IFwiK2JlZ2luK1wiIDw9IFwiK2VuZCtcIiA8PSBcIit0aGlzLmJ1ZmZlci5ieXRlTGVuZ3RoKTtcbiAgICAgICAgfVxyXG4gICAgICAgIHZhciBvdXQgPSBuZXcgQXJyYXkoZW5kIC0gYmVnaW4pLFxyXG4gICAgICAgICAgICBiO1xyXG4gICAgICAgIHdoaWxlIChiZWdpbiA8IGVuZCkge1xyXG4gICAgICAgICAgICBiID0gdGhpcy52aWV3W2JlZ2luKytdO1xyXG4gICAgICAgICAgICBpZiAoYiA8IDB4MTApXHJcbiAgICAgICAgICAgICAgICBvdXQucHVzaChcIjBcIiwgYi50b1N0cmluZygxNikpO1xyXG4gICAgICAgICAgICBlbHNlIG91dC5wdXNoKGIudG9TdHJpbmcoMTYpKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIG91dC5qb2luKCcnKTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWNvZGVzIGEgaGV4IGVuY29kZWQgc3RyaW5nIHRvIGEgQnl0ZUJ1ZmZlci5cclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHIgU3RyaW5nIHRvIGRlY29kZVxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gbGl0dGxlRW5kaWFuIFdoZXRoZXIgdG8gdXNlIGxpdHRsZSBvciBiaWcgZW5kaWFuIGJ5dGUgb3JkZXIuIERlZmF1bHRzIHRvXHJcbiAgICAgKiAge0BsaW5rIEJ5dGVCdWZmZXIuREVGQVVMVF9FTkRJQU59LlxyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gbm9Bc3NlcnQgV2hldGhlciB0byBza2lwIGFzc2VydGlvbnMgb2Ygb2Zmc2V0cyBhbmQgdmFsdWVzLiBEZWZhdWx0cyB0b1xyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyLkRFRkFVTFRfTk9BU1NFUlR9LlxyXG4gICAgICogQHJldHVybnMgeyFCeXRlQnVmZmVyfSBCeXRlQnVmZmVyXHJcbiAgICAgKiBAZXhwb3NlXHJcbiAgICAgKi9cclxuICAgIEJ5dGVCdWZmZXIuZnJvbUhleCA9IGZ1bmN0aW9uKHN0ciwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCkge1xyXG4gICAgICAgIGlmICghbm9Bc3NlcnQpIHtcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBzdHI6IE5vdCBhIHN0cmluZ1wiKTtcclxuICAgICAgICAgICAgaWYgKHN0ci5sZW5ndGggJSAyICE9PSAwKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBzdHI6IExlbmd0aCBub3QgYSBtdWx0aXBsZSBvZiAyXCIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB2YXIgayA9IHN0ci5sZW5ndGgsXHJcbiAgICAgICAgICAgIGJiID0gbmV3IEJ5dGVCdWZmZXIoKGsgLyAyKSB8IDAsIGxpdHRsZUVuZGlhbiksXHJcbiAgICAgICAgICAgIGI7XHJcbiAgICAgICAgZm9yICh2YXIgaT0wLCBqPTA7IGk8azsgaSs9Mikge1xyXG4gICAgICAgICAgICBiID0gcGFyc2VJbnQoc3RyLnN1YnN0cmluZyhpLCBpKzIpLCAxNik7XHJcbiAgICAgICAgICAgIGlmICghbm9Bc3NlcnQpXHJcbiAgICAgICAgICAgICAgICBpZiAoIWlzRmluaXRlKGIpIHx8IGIgPCAwIHx8IGIgPiAyNTUpXHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBzdHI6IENvbnRhaW5zIG5vbi1oZXggY2hhcmFjdGVyc1wiKTtcclxuICAgICAgICAgICAgYmIudmlld1tqKytdID0gYjtcclxuICAgICAgICB9XHJcbiAgICAgICAgYmIubGltaXQgPSBqO1xyXG4gICAgICAgIHJldHVybiBiYjtcclxuICAgIH07XHJcblxyXG4gICAgLy8gdXRmeC1lbWJlZGRhYmxlXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiB1dGZ4LWVtYmVkZGFibGUgKGMpIDIwMTQgRGFuaWVsIFdpcnR6IDxkY29kZUBkY29kZS5pbz5cclxuICAgICAqIFJlbGVhc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjBcclxuICAgICAqIHNlZTogaHR0cHM6Ly9naXRodWIuY29tL2Rjb2RlSU8vdXRmeCBmb3IgZGV0YWlsc1xyXG4gICAgICovXHJcbiAgICB2YXIgdXRmeCA9IGZ1bmN0aW9uKCkge1xyXG4gICAgICAgIFwidXNlIHN0cmljdFwiO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiB1dGZ4IG5hbWVzcGFjZS5cclxuICAgICAgICAgKiBAaW5uZXJcclxuICAgICAgICAgKiBAdHlwZSB7IU9iamVjdC48c3RyaW5nLCo+fVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHZhciB1dGZ4ID0ge307XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIE1heGltdW0gdmFsaWQgY29kZSBwb2ludC5cclxuICAgICAgICAgKiBAdHlwZSB7bnVtYmVyfVxyXG4gICAgICAgICAqIEBjb25zdFxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHV0ZnguTUFYX0NPREVQT0lOVCA9IDB4MTBGRkZGO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBFbmNvZGVzIFVURjggY29kZSBwb2ludHMgdG8gVVRGOCBieXRlcy5cclxuICAgICAgICAgKiBAcGFyYW0geyghZnVuY3Rpb24oKTpudW1iZXJ8bnVsbCkgfCBudW1iZXJ9IHNyYyBDb2RlIHBvaW50cyBzb3VyY2UsIGVpdGhlciBhcyBhIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgbmV4dCBjb2RlIHBvaW50XHJcbiAgICAgICAgICogIHJlc3BlY3RpdmVseSBgbnVsbGAgaWYgdGhlcmUgYXJlIG5vIG1vcmUgY29kZSBwb2ludHMgbGVmdCBvciBhIHNpbmdsZSBudW1lcmljIGNvZGUgcG9pbnQuXHJcbiAgICAgICAgICogQHBhcmFtIHshZnVuY3Rpb24obnVtYmVyKX0gZHN0IEJ5dGVzIGRlc3RpbmF0aW9uIGFzIGEgZnVuY3Rpb24gc3VjY2Vzc2l2ZWx5IGNhbGxlZCB3aXRoIHRoZSBuZXh0IGJ5dGVcclxuICAgICAgICAgKi9cclxuICAgICAgICB1dGZ4LmVuY29kZVVURjggPSBmdW5jdGlvbihzcmMsIGRzdCkge1xyXG4gICAgICAgICAgICB2YXIgY3AgPSBudWxsO1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHNyYyA9PT0gJ251bWJlcicpXHJcbiAgICAgICAgICAgICAgICBjcCA9IHNyYyxcclxuICAgICAgICAgICAgICAgIHNyYyA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gbnVsbDsgfTtcclxuICAgICAgICAgICAgd2hpbGUgKGNwICE9PSBudWxsIHx8IChjcCA9IHNyYygpKSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGNwIDwgMHg4MClcclxuICAgICAgICAgICAgICAgICAgICBkc3QoY3AmMHg3Rik7XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmIChjcCA8IDB4ODAwKVxyXG4gICAgICAgICAgICAgICAgICAgIGRzdCgoKGNwPj42KSYweDFGKXwweEMwKSxcclxuICAgICAgICAgICAgICAgICAgICBkc3QoKGNwJjB4M0YpfDB4ODApO1xyXG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoY3AgPCAweDEwMDAwKVxyXG4gICAgICAgICAgICAgICAgICAgIGRzdCgoKGNwPj4xMikmMHgwRil8MHhFMCksXHJcbiAgICAgICAgICAgICAgICAgICAgZHN0KCgoY3A+PjYpJjB4M0YpfDB4ODApLFxyXG4gICAgICAgICAgICAgICAgICAgIGRzdCgoY3AmMHgzRil8MHg4MCk7XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgZHN0KCgoY3A+PjE4KSYweDA3KXwweEYwKSxcclxuICAgICAgICAgICAgICAgICAgICBkc3QoKChjcD4+MTIpJjB4M0YpfDB4ODApLFxyXG4gICAgICAgICAgICAgICAgICAgIGRzdCgoKGNwPj42KSYweDNGKXwweDgwKSxcclxuICAgICAgICAgICAgICAgICAgICBkc3QoKGNwJjB4M0YpfDB4ODApO1xyXG4gICAgICAgICAgICAgICAgY3AgPSBudWxsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogRGVjb2RlcyBVVEY4IGJ5dGVzIHRvIFVURjggY29kZSBwb2ludHMuXHJcbiAgICAgICAgICogQHBhcmFtIHshZnVuY3Rpb24oKTpudW1iZXJ8bnVsbH0gc3JjIEJ5dGVzIHNvdXJjZSBhcyBhIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgbmV4dCBieXRlIHJlc3BlY3RpdmVseSBgbnVsbGAgaWYgdGhlcmVcclxuICAgICAgICAgKiAgYXJlIG5vIG1vcmUgYnl0ZXMgbGVmdC5cclxuICAgICAgICAgKiBAcGFyYW0geyFmdW5jdGlvbihudW1iZXIpfSBkc3QgQ29kZSBwb2ludHMgZGVzdGluYXRpb24gYXMgYSBmdW5jdGlvbiBzdWNjZXNzaXZlbHkgY2FsbGVkIHdpdGggZWFjaCBkZWNvZGVkIGNvZGUgcG9pbnQuXHJcbiAgICAgICAgICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYSBzdGFydGluZyBieXRlIGlzIGludmFsaWQgaW4gVVRGOFxyXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgbGFzdCBzZXF1ZW5jZSBpcyB0cnVuY2F0ZWQuIEhhcyBhbiBhcnJheSBwcm9wZXJ0eSBgYnl0ZXNgIGhvbGRpbmcgdGhlXHJcbiAgICAgICAgICogIHJlbWFpbmluZyBieXRlcy5cclxuICAgICAgICAgKi9cclxuICAgICAgICB1dGZ4LmRlY29kZVVURjggPSBmdW5jdGlvbihzcmMsIGRzdCkge1xyXG4gICAgICAgICAgICB2YXIgYSwgYiwgYywgZCwgZmFpbCA9IGZ1bmN0aW9uKGIpIHtcclxuICAgICAgICAgICAgICAgIGIgPSBiLnNsaWNlKDAsIGIuaW5kZXhPZihudWxsKSk7XHJcbiAgICAgICAgICAgICAgICB2YXIgZXJyID0gRXJyb3IoYi50b1N0cmluZygpKTtcclxuICAgICAgICAgICAgICAgIGVyci5uYW1lID0gXCJUcnVuY2F0ZWRFcnJvclwiO1xyXG4gICAgICAgICAgICAgICAgZXJyWydieXRlcyddID0gYjtcclxuICAgICAgICAgICAgICAgIHRocm93IGVycjtcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgd2hpbGUgKChhID0gc3JjKCkpICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoKGEmMHg4MCkgPT09IDApXHJcbiAgICAgICAgICAgICAgICAgICAgZHN0KGEpO1xyXG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoKGEmMHhFMCkgPT09IDB4QzApXHJcbiAgICAgICAgICAgICAgICAgICAgKChiID0gc3JjKCkpID09PSBudWxsKSAmJiBmYWlsKFthLCBiXSksXHJcbiAgICAgICAgICAgICAgICAgICAgZHN0KCgoYSYweDFGKTw8NikgfCAoYiYweDNGKSk7XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICgoYSYweEYwKSA9PT0gMHhFMClcclxuICAgICAgICAgICAgICAgICAgICAoKGI9c3JjKCkpID09PSBudWxsIHx8IChjPXNyYygpKSA9PT0gbnVsbCkgJiYgZmFpbChbYSwgYiwgY10pLFxyXG4gICAgICAgICAgICAgICAgICAgIGRzdCgoKGEmMHgwRik8PDEyKSB8ICgoYiYweDNGKTw8NikgfCAoYyYweDNGKSk7XHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmICgoYSYweEY4KSA9PT0gMHhGMClcclxuICAgICAgICAgICAgICAgICAgICAoKGI9c3JjKCkpID09PSBudWxsIHx8IChjPXNyYygpKSA9PT0gbnVsbCB8fCAoZD1zcmMoKSkgPT09IG51bGwpICYmIGZhaWwoW2EsIGIsIGMgLGRdKSxcclxuICAgICAgICAgICAgICAgICAgICBkc3QoKChhJjB4MDcpPDwxOCkgfCAoKGImMHgzRik8PDEyKSB8ICgoYyYweDNGKTw8NikgfCAoZCYweDNGKSk7XHJcbiAgICAgICAgICAgICAgICBlbHNlIHRocm93IFJhbmdlRXJyb3IoXCJJbGxlZ2FsIHN0YXJ0aW5nIGJ5dGU6IFwiK2EpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogQ29udmVydHMgVVRGMTYgY2hhcmFjdGVycyB0byBVVEY4IGNvZGUgcG9pbnRzLlxyXG4gICAgICAgICAqIEBwYXJhbSB7IWZ1bmN0aW9uKCk6bnVtYmVyfG51bGx9IHNyYyBDaGFyYWN0ZXJzIHNvdXJjZSBhcyBhIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgbmV4dCBjaGFyIGNvZGUgcmVzcGVjdGl2ZWx5XHJcbiAgICAgICAgICogIGBudWxsYCBpZiB0aGVyZSBhcmUgbm8gbW9yZSBjaGFyYWN0ZXJzIGxlZnQuXHJcbiAgICAgICAgICogQHBhcmFtIHshZnVuY3Rpb24obnVtYmVyKX0gZHN0IENvZGUgcG9pbnRzIGRlc3RpbmF0aW9uIGFzIGEgZnVuY3Rpb24gc3VjY2Vzc2l2ZWx5IGNhbGxlZCB3aXRoIGVhY2ggY29udmVydGVkIGNvZGVcclxuICAgICAgICAgKiAgcG9pbnQuXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdXRmeC5VVEYxNnRvVVRGOCA9IGZ1bmN0aW9uKHNyYywgZHN0KSB7XHJcbiAgICAgICAgICAgIHZhciBjMSwgYzIgPSBudWxsO1xyXG4gICAgICAgICAgICB3aGlsZSAodHJ1ZSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKChjMSA9IGMyICE9PSBudWxsID8gYzIgOiBzcmMoKSkgPT09IG51bGwpXHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBpZiAoYzEgPj0gMHhEODAwICYmIGMxIDw9IDB4REZGRikge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmICgoYzIgPSBzcmMoKSkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGMyID49IDB4REMwMCAmJiBjMiA8PSAweERGRkYpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRzdCgoYzEtMHhEODAwKSoweDQwMCtjMi0weERDMDArMHgxMDAwMCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjMiA9IG51bGw7IGNvbnRpbnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgZHN0KGMxKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoYzIgIT09IG51bGwpIGRzdChjMik7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogQ29udmVydHMgVVRGOCBjb2RlIHBvaW50cyB0byBVVEYxNiBjaGFyYWN0ZXJzLlxyXG4gICAgICAgICAqIEBwYXJhbSB7KCFmdW5jdGlvbigpOm51bWJlcnxudWxsKSB8IG51bWJlcn0gc3JjIENvZGUgcG9pbnRzIHNvdXJjZSwgZWl0aGVyIGFzIGEgZnVuY3Rpb24gcmV0dXJuaW5nIHRoZSBuZXh0IGNvZGUgcG9pbnRcclxuICAgICAgICAgKiAgcmVzcGVjdGl2ZWx5IGBudWxsYCBpZiB0aGVyZSBhcmUgbm8gbW9yZSBjb2RlIHBvaW50cyBsZWZ0IG9yIGEgc2luZ2xlIG51bWVyaWMgY29kZSBwb2ludC5cclxuICAgICAgICAgKiBAcGFyYW0geyFmdW5jdGlvbihudW1iZXIpfSBkc3QgQ2hhcmFjdGVycyBkZXN0aW5hdGlvbiBhcyBhIGZ1bmN0aW9uIHN1Y2Nlc3NpdmVseSBjYWxsZWQgd2l0aCBlYWNoIGNvbnZlcnRlZCBjaGFyIGNvZGUuXHJcbiAgICAgICAgICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYSBjb2RlIHBvaW50IGlzIG91dCBvZiByYW5nZVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHV0ZnguVVRGOHRvVVRGMTYgPSBmdW5jdGlvbihzcmMsIGRzdCkge1xyXG4gICAgICAgICAgICB2YXIgY3AgPSBudWxsO1xyXG4gICAgICAgICAgICBpZiAodHlwZW9mIHNyYyA9PT0gJ251bWJlcicpXHJcbiAgICAgICAgICAgICAgICBjcCA9IHNyYywgc3JjID0gZnVuY3Rpb24oKSB7IHJldHVybiBudWxsOyB9O1xyXG4gICAgICAgICAgICB3aGlsZSAoY3AgIT09IG51bGwgfHwgKGNwID0gc3JjKCkpICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoY3AgPD0gMHhGRkZGKVxyXG4gICAgICAgICAgICAgICAgICAgIGRzdChjcCk7XHJcbiAgICAgICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICAgICAgY3AgLT0gMHgxMDAwMCxcclxuICAgICAgICAgICAgICAgICAgICBkc3QoKGNwPj4xMCkrMHhEODAwKSxcclxuICAgICAgICAgICAgICAgICAgICBkc3QoKGNwJTB4NDAwKSsweERDMDApO1xyXG4gICAgICAgICAgICAgICAgY3AgPSBudWxsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogQ29udmVydHMgYW5kIGVuY29kZXMgVVRGMTYgY2hhcmFjdGVycyB0byBVVEY4IGJ5dGVzLlxyXG4gICAgICAgICAqIEBwYXJhbSB7IWZ1bmN0aW9uKCk6bnVtYmVyfG51bGx9IHNyYyBDaGFyYWN0ZXJzIHNvdXJjZSBhcyBhIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgbmV4dCBjaGFyIGNvZGUgcmVzcGVjdGl2ZWx5IGBudWxsYFxyXG4gICAgICAgICAqICBpZiB0aGVyZSBhcmUgbm8gbW9yZSBjaGFyYWN0ZXJzIGxlZnQuXHJcbiAgICAgICAgICogQHBhcmFtIHshZnVuY3Rpb24obnVtYmVyKX0gZHN0IEJ5dGVzIGRlc3RpbmF0aW9uIGFzIGEgZnVuY3Rpb24gc3VjY2Vzc2l2ZWx5IGNhbGxlZCB3aXRoIHRoZSBuZXh0IGJ5dGUuXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdXRmeC5lbmNvZGVVVEYxNnRvVVRGOCA9IGZ1bmN0aW9uKHNyYywgZHN0KSB7XHJcbiAgICAgICAgICAgIHV0ZnguVVRGMTZ0b1VURjgoc3JjLCBmdW5jdGlvbihjcCkge1xyXG4gICAgICAgICAgICAgICAgdXRmeC5lbmNvZGVVVEY4KGNwLCBkc3QpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBEZWNvZGVzIGFuZCBjb252ZXJ0cyBVVEY4IGJ5dGVzIHRvIFVURjE2IGNoYXJhY3RlcnMuXHJcbiAgICAgICAgICogQHBhcmFtIHshZnVuY3Rpb24oKTpudW1iZXJ8bnVsbH0gc3JjIEJ5dGVzIHNvdXJjZSBhcyBhIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgbmV4dCBieXRlIHJlc3BlY3RpdmVseSBgbnVsbGAgaWYgdGhlcmVcclxuICAgICAgICAgKiAgYXJlIG5vIG1vcmUgYnl0ZXMgbGVmdC5cclxuICAgICAgICAgKiBAcGFyYW0geyFmdW5jdGlvbihudW1iZXIpfSBkc3QgQ2hhcmFjdGVycyBkZXN0aW5hdGlvbiBhcyBhIGZ1bmN0aW9uIHN1Y2Nlc3NpdmVseSBjYWxsZWQgd2l0aCBlYWNoIGNvbnZlcnRlZCBjaGFyIGNvZGUuXHJcbiAgICAgICAgICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYSBzdGFydGluZyBieXRlIGlzIGludmFsaWQgaW4gVVRGOFxyXG4gICAgICAgICAqIEB0aHJvd3Mge0Vycm9yfSBJZiB0aGUgbGFzdCBzZXF1ZW5jZSBpcyB0cnVuY2F0ZWQuIEhhcyBhbiBhcnJheSBwcm9wZXJ0eSBgYnl0ZXNgIGhvbGRpbmcgdGhlIHJlbWFpbmluZyBieXRlcy5cclxuICAgICAgICAgKi9cclxuICAgICAgICB1dGZ4LmRlY29kZVVURjh0b1VURjE2ID0gZnVuY3Rpb24oc3JjLCBkc3QpIHtcclxuICAgICAgICAgICAgdXRmeC5kZWNvZGVVVEY4KHNyYywgZnVuY3Rpb24oY3ApIHtcclxuICAgICAgICAgICAgICAgIHV0ZnguVVRGOHRvVVRGMTYoY3AsIGRzdCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIENhbGN1bGF0ZXMgdGhlIGJ5dGUgbGVuZ3RoIG9mIGFuIFVURjggY29kZSBwb2ludC5cclxuICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gY3AgVVRGOCBjb2RlIHBvaW50XHJcbiAgICAgICAgICogQHJldHVybnMge251bWJlcn0gQnl0ZSBsZW5ndGhcclxuICAgICAgICAgKi9cclxuICAgICAgICB1dGZ4LmNhbGN1bGF0ZUNvZGVQb2ludCA9IGZ1bmN0aW9uKGNwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAoY3AgPCAweDgwKSA/IDEgOiAoY3AgPCAweDgwMCkgPyAyIDogKGNwIDwgMHgxMDAwMCkgPyAzIDogNDtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBudW1iZXIgb2YgVVRGOCBieXRlcyByZXF1aXJlZCB0byBzdG9yZSBVVEY4IGNvZGUgcG9pbnRzLlxyXG4gICAgICAgICAqIEBwYXJhbSB7KCFmdW5jdGlvbigpOm51bWJlcnxudWxsKX0gc3JjIENvZGUgcG9pbnRzIHNvdXJjZSBhcyBhIGZ1bmN0aW9uIHJldHVybmluZyB0aGUgbmV4dCBjb2RlIHBvaW50IHJlc3BlY3RpdmVseVxyXG4gICAgICAgICAqICBgbnVsbGAgaWYgdGhlcmUgYXJlIG5vIG1vcmUgY29kZSBwb2ludHMgbGVmdC5cclxuICAgICAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBUaGUgbnVtYmVyIG9mIFVURjggYnl0ZXMgcmVxdWlyZWRcclxuICAgICAgICAgKi9cclxuICAgICAgICB1dGZ4LmNhbGN1bGF0ZVVURjggPSBmdW5jdGlvbihzcmMpIHtcclxuICAgICAgICAgICAgdmFyIGNwLCBsPTA7XHJcbiAgICAgICAgICAgIHdoaWxlICgoY3AgPSBzcmMoKSkgIT09IG51bGwpXHJcbiAgICAgICAgICAgICAgICBsICs9IChjcCA8IDB4ODApID8gMSA6IChjcCA8IDB4ODAwKSA/IDIgOiAoY3AgPCAweDEwMDAwKSA/IDMgOiA0O1xyXG4gICAgICAgICAgICByZXR1cm4gbDtcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBDYWxjdWxhdGVzIHRoZSBudW1iZXIgb2YgVVRGOCBjb2RlIHBvaW50cyByZXNwZWN0aXZlbHkgVVRGOCBieXRlcyByZXF1aXJlZCB0byBzdG9yZSBVVEYxNiBjaGFyIGNvZGVzLlxyXG4gICAgICAgICAqIEBwYXJhbSB7KCFmdW5jdGlvbigpOm51bWJlcnxudWxsKX0gc3JjIENoYXJhY3RlcnMgc291cmNlIGFzIGEgZnVuY3Rpb24gcmV0dXJuaW5nIHRoZSBuZXh0IGNoYXIgY29kZSByZXNwZWN0aXZlbHlcclxuICAgICAgICAgKiAgYG51bGxgIGlmIHRoZXJlIGFyZSBubyBtb3JlIGNoYXJhY3RlcnMgbGVmdC5cclxuICAgICAgICAgKiBAcmV0dXJucyB7IUFycmF5LjxudW1iZXI+fSBUaGUgbnVtYmVyIG9mIFVURjggY29kZSBwb2ludHMgYXQgaW5kZXggMCBhbmQgdGhlIG51bWJlciBvZiBVVEY4IGJ5dGVzIHJlcXVpcmVkIGF0IGluZGV4IDEuXHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdXRmeC5jYWxjdWxhdGVVVEYxNmFzVVRGOCA9IGZ1bmN0aW9uKHNyYykge1xyXG4gICAgICAgICAgICB2YXIgbj0wLCBsPTA7XHJcbiAgICAgICAgICAgIHV0ZnguVVRGMTZ0b1VURjgoc3JjLCBmdW5jdGlvbihjcCkge1xyXG4gICAgICAgICAgICAgICAgKytuOyBsICs9IChjcCA8IDB4ODApID8gMSA6IChjcCA8IDB4ODAwKSA/IDIgOiAoY3AgPCAweDEwMDAwKSA/IDMgOiA0O1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgcmV0dXJuIFtuLGxdO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHJldHVybiB1dGZ4O1xyXG4gICAgfSgpO1xyXG5cclxuICAgIC8vIGVuY29kaW5ncy91dGY4XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBFbmNvZGVzIHRoaXMgQnl0ZUJ1ZmZlcidzIGNvbnRlbnRzIGJldHdlZW4ge0BsaW5rIEJ5dGVCdWZmZXIjb2Zmc2V0fSBhbmQge0BsaW5rIEJ5dGVCdWZmZXIjbGltaXR9IHRvIGFuIFVURjggZW5jb2RlZFxyXG4gICAgICogIHN0cmluZy5cclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IEhleCBlbmNvZGVkIHN0cmluZ1xyXG4gICAgICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYG9mZnNldCA+IGxpbWl0YFxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyUHJvdG90eXBlLnRvVVRGOCA9IGZ1bmN0aW9uKGJlZ2luLCBlbmQpIHtcclxuICAgICAgICBpZiAodHlwZW9mIGJlZ2luID09PSAndW5kZWZpbmVkJykgYmVnaW4gPSB0aGlzLm9mZnNldDtcclxuICAgICAgICBpZiAodHlwZW9mIGVuZCA9PT0gJ3VuZGVmaW5lZCcpIGVuZCA9IHRoaXMubGltaXQ7XHJcbiAgICAgICAgaWYgKCF0aGlzLm5vQXNzZXJ0KSB7XHJcbiAgICAgICAgICAgIGlmICh0eXBlb2YgYmVnaW4gIT09ICdudW1iZXInIHx8IGJlZ2luICUgMSAhPT0gMClcbiAgICAgICAgICAgICAgICB0aHJvdyBUeXBlRXJyb3IoXCJJbGxlZ2FsIGJlZ2luOiBOb3QgYW4gaW50ZWdlclwiKTtcbiAgICAgICAgICAgIGJlZ2luID4+Pj0gMDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZW5kICE9PSAnbnVtYmVyJyB8fCBlbmQgJSAxICE9PSAwKVxuICAgICAgICAgICAgICAgIHRocm93IFR5cGVFcnJvcihcIklsbGVnYWwgZW5kOiBOb3QgYW4gaW50ZWdlclwiKTtcbiAgICAgICAgICAgIGVuZCA+Pj49IDA7XG4gICAgICAgICAgICBpZiAoYmVnaW4gPCAwIHx8IGJlZ2luID4gZW5kIHx8IGVuZCA+IHRoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpXG4gICAgICAgICAgICAgICAgdGhyb3cgUmFuZ2VFcnJvcihcIklsbGVnYWwgcmFuZ2U6IDAgPD0gXCIrYmVnaW4rXCIgPD0gXCIrZW5kK1wiIDw9IFwiK3RoaXMuYnVmZmVyLmJ5dGVMZW5ndGgpO1xuICAgICAgICB9XHJcbiAgICAgICAgdmFyIHNkOyB0cnkge1xyXG4gICAgICAgICAgICB1dGZ4LmRlY29kZVVURjh0b1VURjE2KGZ1bmN0aW9uKCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGJlZ2luIDwgZW5kID8gdGhpcy52aWV3W2JlZ2luKytdIDogbnVsbDtcclxuICAgICAgICAgICAgfS5iaW5kKHRoaXMpLCBzZCA9IHN0cmluZ0Rlc3RpbmF0aW9uKCkpO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgaWYgKGJlZ2luICE9PSBlbmQpXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKFwiSWxsZWdhbCByYW5nZTogVHJ1bmNhdGVkIGRhdGEsIFwiK2JlZ2luK1wiICE9IFwiK2VuZCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBzZCgpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlY29kZXMgYW4gVVRGOCBlbmNvZGVkIHN0cmluZyB0byBhIEJ5dGVCdWZmZXIuXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFN0cmluZyB0byBkZWNvZGVcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IGxpdHRsZUVuZGlhbiBXaGV0aGVyIHRvIHVzZSBsaXR0bGUgb3IgYmlnIGVuZGlhbiBieXRlIG9yZGVyLiBEZWZhdWx0cyB0b1xyXG4gICAgICogIHtAbGluayBCeXRlQnVmZmVyLkRFRkFVTFRfRU5ESUFOfS5cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IG5vQXNzZXJ0IFdoZXRoZXIgdG8gc2tpcCBhc3NlcnRpb25zIG9mIG9mZnNldHMgYW5kIHZhbHVlcy4gRGVmYXVsdHMgdG9cclxuICAgICAqICB7QGxpbmsgQnl0ZUJ1ZmZlci5ERUZBVUxUX05PQVNTRVJUfS5cclxuICAgICAqIEByZXR1cm5zIHshQnl0ZUJ1ZmZlcn0gQnl0ZUJ1ZmZlclxyXG4gICAgICogQGV4cG9zZVxyXG4gICAgICovXHJcbiAgICBCeXRlQnVmZmVyLmZyb21VVEY4ID0gZnVuY3Rpb24oc3RyLCBsaXR0bGVFbmRpYW4sIG5vQXNzZXJ0KSB7XHJcbiAgICAgICAgaWYgKCFub0Fzc2VydClcclxuICAgICAgICAgICAgaWYgKHR5cGVvZiBzdHIgIT09ICdzdHJpbmcnKVxyXG4gICAgICAgICAgICAgICAgdGhyb3cgVHlwZUVycm9yKFwiSWxsZWdhbCBzdHI6IE5vdCBhIHN0cmluZ1wiKTtcclxuICAgICAgICB2YXIgYmIgPSBuZXcgQnl0ZUJ1ZmZlcih1dGZ4LmNhbGN1bGF0ZVVURjE2YXNVVEY4KHN0cmluZ1NvdXJjZShzdHIpLCB0cnVlKVsxXSwgbGl0dGxlRW5kaWFuLCBub0Fzc2VydCksXHJcbiAgICAgICAgICAgIGkgPSAwO1xyXG4gICAgICAgIHV0ZnguZW5jb2RlVVRGMTZ0b1VURjgoc3RyaW5nU291cmNlKHN0ciksIGZ1bmN0aW9uKGIpIHtcclxuICAgICAgICAgICAgYmIudmlld1tpKytdID0gYjtcclxuICAgICAgICB9KTtcclxuICAgICAgICBiYi5saW1pdCA9IGk7XHJcbiAgICAgICAgcmV0dXJuIGJiO1xyXG4gICAgfTtcclxuXHJcbiAgICByZXR1cm4gQnl0ZUJ1ZmZlcjtcclxufSk7XHJcbiIsInZhciBCdWZmZXIgPSByZXF1aXJlKCdzYWZlLWJ1ZmZlcicpLkJ1ZmZlclxudmFyIFRyYW5zZm9ybSA9IHJlcXVpcmUoJ3N0cmVhbScpLlRyYW5zZm9ybVxudmFyIFN0cmluZ0RlY29kZXIgPSByZXF1aXJlKCdzdHJpbmdfZGVjb2RlcicpLlN0cmluZ0RlY29kZXJcbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJylcblxuZnVuY3Rpb24gQ2lwaGVyQmFzZSAoaGFzaE1vZGUpIHtcbiAgVHJhbnNmb3JtLmNhbGwodGhpcylcbiAgdGhpcy5oYXNoTW9kZSA9IHR5cGVvZiBoYXNoTW9kZSA9PT0gJ3N0cmluZydcbiAgaWYgKHRoaXMuaGFzaE1vZGUpIHtcbiAgICB0aGlzW2hhc2hNb2RlXSA9IHRoaXMuX2ZpbmFsT3JEaWdlc3RcbiAgfSBlbHNlIHtcbiAgICB0aGlzLmZpbmFsID0gdGhpcy5fZmluYWxPckRpZ2VzdFxuICB9XG4gIGlmICh0aGlzLl9maW5hbCkge1xuICAgIHRoaXMuX19maW5hbCA9IHRoaXMuX2ZpbmFsXG4gICAgdGhpcy5fZmluYWwgPSBudWxsXG4gIH1cbiAgdGhpcy5fZGVjb2RlciA9IG51bGxcbiAgdGhpcy5fZW5jb2RpbmcgPSBudWxsXG59XG5pbmhlcml0cyhDaXBoZXJCYXNlLCBUcmFuc2Zvcm0pXG5cbkNpcGhlckJhc2UucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChkYXRhLCBpbnB1dEVuYywgb3V0cHV0RW5jKSB7XG4gIGlmICh0eXBlb2YgZGF0YSA9PT0gJ3N0cmluZycpIHtcbiAgICBkYXRhID0gQnVmZmVyLmZyb20oZGF0YSwgaW5wdXRFbmMpXG4gIH1cblxuICB2YXIgb3V0RGF0YSA9IHRoaXMuX3VwZGF0ZShkYXRhKVxuICBpZiAodGhpcy5oYXNoTW9kZSkgcmV0dXJuIHRoaXNcblxuICBpZiAob3V0cHV0RW5jKSB7XG4gICAgb3V0RGF0YSA9IHRoaXMuX3RvU3RyaW5nKG91dERhdGEsIG91dHB1dEVuYylcbiAgfVxuXG4gIHJldHVybiBvdXREYXRhXG59XG5cbkNpcGhlckJhc2UucHJvdG90eXBlLnNldEF1dG9QYWRkaW5nID0gZnVuY3Rpb24gKCkge31cbkNpcGhlckJhc2UucHJvdG90eXBlLmdldEF1dGhUYWcgPSBmdW5jdGlvbiAoKSB7XG4gIHRocm93IG5ldyBFcnJvcigndHJ5aW5nIHRvIGdldCBhdXRoIHRhZyBpbiB1bnN1cHBvcnRlZCBzdGF0ZScpXG59XG5cbkNpcGhlckJhc2UucHJvdG90eXBlLnNldEF1dGhUYWcgPSBmdW5jdGlvbiAoKSB7XG4gIHRocm93IG5ldyBFcnJvcigndHJ5aW5nIHRvIHNldCBhdXRoIHRhZyBpbiB1bnN1cHBvcnRlZCBzdGF0ZScpXG59XG5cbkNpcGhlckJhc2UucHJvdG90eXBlLnNldEFBRCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCd0cnlpbmcgdG8gc2V0IGFhZCBpbiB1bnN1cHBvcnRlZCBzdGF0ZScpXG59XG5cbkNpcGhlckJhc2UucHJvdG90eXBlLl90cmFuc2Zvcm0gPSBmdW5jdGlvbiAoZGF0YSwgXywgbmV4dCkge1xuICB2YXIgZXJyXG4gIHRyeSB7XG4gICAgaWYgKHRoaXMuaGFzaE1vZGUpIHtcbiAgICAgIHRoaXMuX3VwZGF0ZShkYXRhKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnB1c2godGhpcy5fdXBkYXRlKGRhdGEpKVxuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIGVyciA9IGVcbiAgfSBmaW5hbGx5IHtcbiAgICBuZXh0KGVycilcbiAgfVxufVxuQ2lwaGVyQmFzZS5wcm90b3R5cGUuX2ZsdXNoID0gZnVuY3Rpb24gKGRvbmUpIHtcbiAgdmFyIGVyclxuICB0cnkge1xuICAgIHRoaXMucHVzaCh0aGlzLl9fZmluYWwoKSlcbiAgfSBjYXRjaCAoZSkge1xuICAgIGVyciA9IGVcbiAgfVxuXG4gIGRvbmUoZXJyKVxufVxuQ2lwaGVyQmFzZS5wcm90b3R5cGUuX2ZpbmFsT3JEaWdlc3QgPSBmdW5jdGlvbiAob3V0cHV0RW5jKSB7XG4gIHZhciBvdXREYXRhID0gdGhpcy5fX2ZpbmFsKCkgfHwgQnVmZmVyLmFsbG9jKDApXG4gIGlmIChvdXRwdXRFbmMpIHtcbiAgICBvdXREYXRhID0gdGhpcy5fdG9TdHJpbmcob3V0RGF0YSwgb3V0cHV0RW5jLCB0cnVlKVxuICB9XG4gIHJldHVybiBvdXREYXRhXG59XG5cbkNpcGhlckJhc2UucHJvdG90eXBlLl90b1N0cmluZyA9IGZ1bmN0aW9uICh2YWx1ZSwgZW5jLCBmaW4pIHtcbiAgaWYgKCF0aGlzLl9kZWNvZGVyKSB7XG4gICAgdGhpcy5fZGVjb2RlciA9IG5ldyBTdHJpbmdEZWNvZGVyKGVuYylcbiAgICB0aGlzLl9lbmNvZGluZyA9IGVuY1xuICB9XG5cbiAgaWYgKHRoaXMuX2VuY29kaW5nICE9PSBlbmMpIHRocm93IG5ldyBFcnJvcignY2FuXFwndCBzd2l0Y2ggZW5jb2RpbmdzJylcblxuICB2YXIgb3V0ID0gdGhpcy5fZGVjb2Rlci53cml0ZSh2YWx1ZSlcbiAgaWYgKGZpbikge1xuICAgIG91dCArPSB0aGlzLl9kZWNvZGVyLmVuZCgpXG4gIH1cblxuICByZXR1cm4gb3V0XG59XG5cbm1vZHVsZS5leHBvcnRzID0gQ2lwaGVyQmFzZVxuIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIE5PVEU6IFRoZXNlIHR5cGUgY2hlY2tpbmcgZnVuY3Rpb25zIGludGVudGlvbmFsbHkgZG9uJ3QgdXNlIGBpbnN0YW5jZW9mYFxuLy8gYmVjYXVzZSBpdCBpcyBmcmFnaWxlIGFuZCBjYW4gYmUgZWFzaWx5IGZha2VkIHdpdGggYE9iamVjdC5jcmVhdGUoKWAuXG5cbmZ1bmN0aW9uIGlzQXJyYXkoYXJnKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KSB7XG4gICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYXJnKTtcbiAgfVxuICByZXR1cm4gb2JqZWN0VG9TdHJpbmcoYXJnKSA9PT0gJ1tvYmplY3QgQXJyYXldJztcbn1cbmV4cG9ydHMuaXNBcnJheSA9IGlzQXJyYXk7XG5cbmZ1bmN0aW9uIGlzQm9vbGVhbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdib29sZWFuJztcbn1cbmV4cG9ydHMuaXNCb29sZWFuID0gaXNCb29sZWFuO1xuXG5mdW5jdGlvbiBpc051bGwoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbCA9IGlzTnVsbDtcblxuZnVuY3Rpb24gaXNOdWxsT3JVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT0gbnVsbDtcbn1cbmV4cG9ydHMuaXNOdWxsT3JVbmRlZmluZWQgPSBpc051bGxPclVuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNOdW1iZXIoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnbnVtYmVyJztcbn1cbmV4cG9ydHMuaXNOdW1iZXIgPSBpc051bWJlcjtcblxuZnVuY3Rpb24gaXNTdHJpbmcoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnc3RyaW5nJztcbn1cbmV4cG9ydHMuaXNTdHJpbmcgPSBpc1N0cmluZztcblxuZnVuY3Rpb24gaXNTeW1ib2woYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnc3ltYm9sJztcbn1cbmV4cG9ydHMuaXNTeW1ib2wgPSBpc1N5bWJvbDtcblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbmV4cG9ydHMuaXNVbmRlZmluZWQgPSBpc1VuZGVmaW5lZDtcblxuZnVuY3Rpb24gaXNSZWdFeHAocmUpIHtcbiAgcmV0dXJuIG9iamVjdFRvU3RyaW5nKHJlKSA9PT0gJ1tvYmplY3QgUmVnRXhwXSc7XG59XG5leHBvcnRzLmlzUmVnRXhwID0gaXNSZWdFeHA7XG5cbmZ1bmN0aW9uIGlzT2JqZWN0KGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ29iamVjdCcgJiYgYXJnICE9PSBudWxsO1xufVxuZXhwb3J0cy5pc09iamVjdCA9IGlzT2JqZWN0O1xuXG5mdW5jdGlvbiBpc0RhdGUoZCkge1xuICByZXR1cm4gb2JqZWN0VG9TdHJpbmcoZCkgPT09ICdbb2JqZWN0IERhdGVdJztcbn1cbmV4cG9ydHMuaXNEYXRlID0gaXNEYXRlO1xuXG5mdW5jdGlvbiBpc0Vycm9yKGUpIHtcbiAgcmV0dXJuIChvYmplY3RUb1N0cmluZyhlKSA9PT0gJ1tvYmplY3QgRXJyb3JdJyB8fCBlIGluc3RhbmNlb2YgRXJyb3IpO1xufVxuZXhwb3J0cy5pc0Vycm9yID0gaXNFcnJvcjtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5leHBvcnRzLmlzRnVuY3Rpb24gPSBpc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbCB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnIHx8ICAvLyBFUzYgc3ltYm9sXG4gICAgICAgICB0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJztcbn1cbmV4cG9ydHMuaXNQcmltaXRpdmUgPSBpc1ByaW1pdGl2ZTtcblxuZXhwb3J0cy5pc0J1ZmZlciA9IEJ1ZmZlci5pc0J1ZmZlcjtcblxuZnVuY3Rpb24gb2JqZWN0VG9TdHJpbmcobykge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG8pO1xufVxuIiwiJ3VzZSBzdHJpY3QnXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpXG52YXIgTUQ1ID0gcmVxdWlyZSgnbWQ1LmpzJylcbnZhciBSSVBFTUQxNjAgPSByZXF1aXJlKCdyaXBlbWQxNjAnKVxudmFyIHNoYSA9IHJlcXVpcmUoJ3NoYS5qcycpXG52YXIgQmFzZSA9IHJlcXVpcmUoJ2NpcGhlci1iYXNlJylcblxuZnVuY3Rpb24gSGFzaCAoaGFzaCkge1xuICBCYXNlLmNhbGwodGhpcywgJ2RpZ2VzdCcpXG5cbiAgdGhpcy5faGFzaCA9IGhhc2hcbn1cblxuaW5oZXJpdHMoSGFzaCwgQmFzZSlcblxuSGFzaC5wcm90b3R5cGUuX3VwZGF0ZSA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gIHRoaXMuX2hhc2gudXBkYXRlKGRhdGEpXG59XG5cbkhhc2gucHJvdG90eXBlLl9maW5hbCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMuX2hhc2guZGlnZXN0KClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGVIYXNoIChhbGcpIHtcbiAgYWxnID0gYWxnLnRvTG93ZXJDYXNlKClcbiAgaWYgKGFsZyA9PT0gJ21kNScpIHJldHVybiBuZXcgTUQ1KClcbiAgaWYgKGFsZyA9PT0gJ3JtZDE2MCcgfHwgYWxnID09PSAncmlwZW1kMTYwJykgcmV0dXJuIG5ldyBSSVBFTUQxNjAoKVxuXG4gIHJldHVybiBuZXcgSGFzaChzaGEoYWxnKSlcbn1cbiIsInZhciBNRDUgPSByZXF1aXJlKCdtZDUuanMnKVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChidWZmZXIpIHtcbiAgcmV0dXJuIG5ldyBNRDUoKS51cGRhdGUoYnVmZmVyKS5kaWdlc3QoKVxufVxuIiwiJ3VzZSBzdHJpY3QnXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpXG52YXIgTGVnYWN5ID0gcmVxdWlyZSgnLi9sZWdhY3knKVxudmFyIEJhc2UgPSByZXF1aXJlKCdjaXBoZXItYmFzZScpXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnc2FmZS1idWZmZXInKS5CdWZmZXJcbnZhciBtZDUgPSByZXF1aXJlKCdjcmVhdGUtaGFzaC9tZDUnKVxudmFyIFJJUEVNRDE2MCA9IHJlcXVpcmUoJ3JpcGVtZDE2MCcpXG5cbnZhciBzaGEgPSByZXF1aXJlKCdzaGEuanMnKVxuXG52YXIgWkVST1MgPSBCdWZmZXIuYWxsb2MoMTI4KVxuXG5mdW5jdGlvbiBIbWFjIChhbGcsIGtleSkge1xuICBCYXNlLmNhbGwodGhpcywgJ2RpZ2VzdCcpXG4gIGlmICh0eXBlb2Yga2V5ID09PSAnc3RyaW5nJykge1xuICAgIGtleSA9IEJ1ZmZlci5mcm9tKGtleSlcbiAgfVxuXG4gIHZhciBibG9ja3NpemUgPSAoYWxnID09PSAnc2hhNTEyJyB8fCBhbGcgPT09ICdzaGEzODQnKSA/IDEyOCA6IDY0XG5cbiAgdGhpcy5fYWxnID0gYWxnXG4gIHRoaXMuX2tleSA9IGtleVxuICBpZiAoa2V5Lmxlbmd0aCA+IGJsb2Nrc2l6ZSkge1xuICAgIHZhciBoYXNoID0gYWxnID09PSAncm1kMTYwJyA/IG5ldyBSSVBFTUQxNjAoKSA6IHNoYShhbGcpXG4gICAga2V5ID0gaGFzaC51cGRhdGUoa2V5KS5kaWdlc3QoKVxuICB9IGVsc2UgaWYgKGtleS5sZW5ndGggPCBibG9ja3NpemUpIHtcbiAgICBrZXkgPSBCdWZmZXIuY29uY2F0KFtrZXksIFpFUk9TXSwgYmxvY2tzaXplKVxuICB9XG5cbiAgdmFyIGlwYWQgPSB0aGlzLl9pcGFkID0gQnVmZmVyLmFsbG9jVW5zYWZlKGJsb2Nrc2l6ZSlcbiAgdmFyIG9wYWQgPSB0aGlzLl9vcGFkID0gQnVmZmVyLmFsbG9jVW5zYWZlKGJsb2Nrc2l6ZSlcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IGJsb2Nrc2l6ZTsgaSsrKSB7XG4gICAgaXBhZFtpXSA9IGtleVtpXSBeIDB4MzZcbiAgICBvcGFkW2ldID0ga2V5W2ldIF4gMHg1Q1xuICB9XG4gIHRoaXMuX2hhc2ggPSBhbGcgPT09ICdybWQxNjAnID8gbmV3IFJJUEVNRDE2MCgpIDogc2hhKGFsZylcbiAgdGhpcy5faGFzaC51cGRhdGUoaXBhZClcbn1cblxuaW5oZXJpdHMoSG1hYywgQmFzZSlcblxuSG1hYy5wcm90b3R5cGUuX3VwZGF0ZSA9IGZ1bmN0aW9uIChkYXRhKSB7XG4gIHRoaXMuX2hhc2gudXBkYXRlKGRhdGEpXG59XG5cbkhtYWMucHJvdG90eXBlLl9maW5hbCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIGggPSB0aGlzLl9oYXNoLmRpZ2VzdCgpXG4gIHZhciBoYXNoID0gdGhpcy5fYWxnID09PSAncm1kMTYwJyA/IG5ldyBSSVBFTUQxNjAoKSA6IHNoYSh0aGlzLl9hbGcpXG4gIHJldHVybiBoYXNoLnVwZGF0ZSh0aGlzLl9vcGFkKS51cGRhdGUoaCkuZGlnZXN0KClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBjcmVhdGVIbWFjIChhbGcsIGtleSkge1xuICBhbGcgPSBhbGcudG9Mb3dlckNhc2UoKVxuICBpZiAoYWxnID09PSAncm1kMTYwJyB8fCBhbGcgPT09ICdyaXBlbWQxNjAnKSB7XG4gICAgcmV0dXJuIG5ldyBIbWFjKCdybWQxNjAnLCBrZXkpXG4gIH1cbiAgaWYgKGFsZyA9PT0gJ21kNScpIHtcbiAgICByZXR1cm4gbmV3IExlZ2FjeShtZDUsIGtleSlcbiAgfVxuICByZXR1cm4gbmV3IEhtYWMoYWxnLCBrZXkpXG59XG4iLCIndXNlIHN0cmljdCdcbnZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJylcbnZhciBCdWZmZXIgPSByZXF1aXJlKCdzYWZlLWJ1ZmZlcicpLkJ1ZmZlclxuXG52YXIgQmFzZSA9IHJlcXVpcmUoJ2NpcGhlci1iYXNlJylcblxudmFyIFpFUk9TID0gQnVmZmVyLmFsbG9jKDEyOClcbnZhciBibG9ja3NpemUgPSA2NFxuXG5mdW5jdGlvbiBIbWFjIChhbGcsIGtleSkge1xuICBCYXNlLmNhbGwodGhpcywgJ2RpZ2VzdCcpXG4gIGlmICh0eXBlb2Yga2V5ID09PSAnc3RyaW5nJykge1xuICAgIGtleSA9IEJ1ZmZlci5mcm9tKGtleSlcbiAgfVxuXG4gIHRoaXMuX2FsZyA9IGFsZ1xuICB0aGlzLl9rZXkgPSBrZXlcblxuICBpZiAoa2V5Lmxlbmd0aCA+IGJsb2Nrc2l6ZSkge1xuICAgIGtleSA9IGFsZyhrZXkpXG4gIH0gZWxzZSBpZiAoa2V5Lmxlbmd0aCA8IGJsb2Nrc2l6ZSkge1xuICAgIGtleSA9IEJ1ZmZlci5jb25jYXQoW2tleSwgWkVST1NdLCBibG9ja3NpemUpXG4gIH1cblxuICB2YXIgaXBhZCA9IHRoaXMuX2lwYWQgPSBCdWZmZXIuYWxsb2NVbnNhZmUoYmxvY2tzaXplKVxuICB2YXIgb3BhZCA9IHRoaXMuX29wYWQgPSBCdWZmZXIuYWxsb2NVbnNhZmUoYmxvY2tzaXplKVxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tzaXplOyBpKyspIHtcbiAgICBpcGFkW2ldID0ga2V5W2ldIF4gMHgzNlxuICAgIG9wYWRbaV0gPSBrZXlbaV0gXiAweDVDXG4gIH1cblxuICB0aGlzLl9oYXNoID0gW2lwYWRdXG59XG5cbmluaGVyaXRzKEhtYWMsIEJhc2UpXG5cbkhtYWMucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbiAoZGF0YSkge1xuICB0aGlzLl9oYXNoLnB1c2goZGF0YSlcbn1cblxuSG1hYy5wcm90b3R5cGUuX2ZpbmFsID0gZnVuY3Rpb24gKCkge1xuICB2YXIgaCA9IHRoaXMuX2FsZyhCdWZmZXIuY29uY2F0KHRoaXMuX2hhc2gpKVxuICByZXR1cm4gdGhpcy5fYWxnKEJ1ZmZlci5jb25jYXQoW3RoaXMuX29wYWQsIGhdKSlcbn1cbm1vZHVsZS5leHBvcnRzID0gSG1hY1xuIiwiOyhmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSwgdW5kZWYpIHtcblx0aWYgKHR5cGVvZiBleHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoXCIuL2NvcmVcIiksIHJlcXVpcmUoXCIuL2VuYy1iYXNlNjRcIiksIHJlcXVpcmUoXCIuL21kNVwiKSwgcmVxdWlyZShcIi4vZXZwa2RmXCIpLCByZXF1aXJlKFwiLi9jaXBoZXItY29yZVwiKSk7XG5cdH1cblx0ZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoW1wiLi9jb3JlXCIsIFwiLi9lbmMtYmFzZTY0XCIsIFwiLi9tZDVcIiwgXCIuL2V2cGtkZlwiLCBcIi4vY2lwaGVyLWNvcmVcIl0sIGZhY3RvcnkpO1xuXHR9XG5cdGVsc2Uge1xuXHRcdC8vIEdsb2JhbCAoYnJvd3Nlcilcblx0XHRmYWN0b3J5KHJvb3QuQ3J5cHRvSlMpO1xuXHR9XG59KHRoaXMsIGZ1bmN0aW9uIChDcnlwdG9KUykge1xuXG5cdChmdW5jdGlvbiAoKSB7XG5cdCAgICAvLyBTaG9ydGN1dHNcblx0ICAgIHZhciBDID0gQ3J5cHRvSlM7XG5cdCAgICB2YXIgQ19saWIgPSBDLmxpYjtcblx0ICAgIHZhciBCbG9ja0NpcGhlciA9IENfbGliLkJsb2NrQ2lwaGVyO1xuXHQgICAgdmFyIENfYWxnbyA9IEMuYWxnbztcblxuXHQgICAgLy8gTG9va3VwIHRhYmxlc1xuXHQgICAgdmFyIFNCT1ggPSBbXTtcblx0ICAgIHZhciBJTlZfU0JPWCA9IFtdO1xuXHQgICAgdmFyIFNVQl9NSVhfMCA9IFtdO1xuXHQgICAgdmFyIFNVQl9NSVhfMSA9IFtdO1xuXHQgICAgdmFyIFNVQl9NSVhfMiA9IFtdO1xuXHQgICAgdmFyIFNVQl9NSVhfMyA9IFtdO1xuXHQgICAgdmFyIElOVl9TVUJfTUlYXzAgPSBbXTtcblx0ICAgIHZhciBJTlZfU1VCX01JWF8xID0gW107XG5cdCAgICB2YXIgSU5WX1NVQl9NSVhfMiA9IFtdO1xuXHQgICAgdmFyIElOVl9TVUJfTUlYXzMgPSBbXTtcblxuXHQgICAgLy8gQ29tcHV0ZSBsb29rdXAgdGFibGVzXG5cdCAgICAoZnVuY3Rpb24gKCkge1xuXHQgICAgICAgIC8vIENvbXB1dGUgZG91YmxlIHRhYmxlXG5cdCAgICAgICAgdmFyIGQgPSBbXTtcblx0ICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG5cdCAgICAgICAgICAgIGlmIChpIDwgMTI4KSB7XG5cdCAgICAgICAgICAgICAgICBkW2ldID0gaSA8PCAxO1xuXHQgICAgICAgICAgICB9IGVsc2Uge1xuXHQgICAgICAgICAgICAgICAgZFtpXSA9IChpIDw8IDEpIF4gMHgxMWI7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICB9XG5cblx0ICAgICAgICAvLyBXYWxrIEdGKDJeOClcblx0ICAgICAgICB2YXIgeCA9IDA7XG5cdCAgICAgICAgdmFyIHhpID0gMDtcblx0ICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDI1NjsgaSsrKSB7XG5cdCAgICAgICAgICAgIC8vIENvbXB1dGUgc2JveFxuXHQgICAgICAgICAgICB2YXIgc3ggPSB4aSBeICh4aSA8PCAxKSBeICh4aSA8PCAyKSBeICh4aSA8PCAzKSBeICh4aSA8PCA0KTtcblx0ICAgICAgICAgICAgc3ggPSAoc3ggPj4+IDgpIF4gKHN4ICYgMHhmZikgXiAweDYzO1xuXHQgICAgICAgICAgICBTQk9YW3hdID0gc3g7XG5cdCAgICAgICAgICAgIElOVl9TQk9YW3N4XSA9IHg7XG5cblx0ICAgICAgICAgICAgLy8gQ29tcHV0ZSBtdWx0aXBsaWNhdGlvblxuXHQgICAgICAgICAgICB2YXIgeDIgPSBkW3hdO1xuXHQgICAgICAgICAgICB2YXIgeDQgPSBkW3gyXTtcblx0ICAgICAgICAgICAgdmFyIHg4ID0gZFt4NF07XG5cblx0ICAgICAgICAgICAgLy8gQ29tcHV0ZSBzdWIgYnl0ZXMsIG1peCBjb2x1bW5zIHRhYmxlc1xuXHQgICAgICAgICAgICB2YXIgdCA9IChkW3N4XSAqIDB4MTAxKSBeIChzeCAqIDB4MTAxMDEwMCk7XG5cdCAgICAgICAgICAgIFNVQl9NSVhfMFt4XSA9ICh0IDw8IDI0KSB8ICh0ID4+PiA4KTtcblx0ICAgICAgICAgICAgU1VCX01JWF8xW3hdID0gKHQgPDwgMTYpIHwgKHQgPj4+IDE2KTtcblx0ICAgICAgICAgICAgU1VCX01JWF8yW3hdID0gKHQgPDwgOCkgIHwgKHQgPj4+IDI0KTtcblx0ICAgICAgICAgICAgU1VCX01JWF8zW3hdID0gdDtcblxuXHQgICAgICAgICAgICAvLyBDb21wdXRlIGludiBzdWIgYnl0ZXMsIGludiBtaXggY29sdW1ucyB0YWJsZXNcblx0ICAgICAgICAgICAgdmFyIHQgPSAoeDggKiAweDEwMTAxMDEpIF4gKHg0ICogMHgxMDAwMSkgXiAoeDIgKiAweDEwMSkgXiAoeCAqIDB4MTAxMDEwMCk7XG5cdCAgICAgICAgICAgIElOVl9TVUJfTUlYXzBbc3hdID0gKHQgPDwgMjQpIHwgKHQgPj4+IDgpO1xuXHQgICAgICAgICAgICBJTlZfU1VCX01JWF8xW3N4XSA9ICh0IDw8IDE2KSB8ICh0ID4+PiAxNik7XG5cdCAgICAgICAgICAgIElOVl9TVUJfTUlYXzJbc3hdID0gKHQgPDwgOCkgIHwgKHQgPj4+IDI0KTtcblx0ICAgICAgICAgICAgSU5WX1NVQl9NSVhfM1tzeF0gPSB0O1xuXG5cdCAgICAgICAgICAgIC8vIENvbXB1dGUgbmV4dCBjb3VudGVyXG5cdCAgICAgICAgICAgIGlmICgheCkge1xuXHQgICAgICAgICAgICAgICAgeCA9IHhpID0gMTtcblx0ICAgICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIHggPSB4MiBeIGRbZFtkW3g4IF4geDJdXV07XG5cdCAgICAgICAgICAgICAgICB4aSBePSBkW2RbeGldXTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgIH0oKSk7XG5cblx0ICAgIC8vIFByZWNvbXB1dGVkIFJjb24gbG9va3VwXG5cdCAgICB2YXIgUkNPTiA9IFsweDAwLCAweDAxLCAweDAyLCAweDA0LCAweDA4LCAweDEwLCAweDIwLCAweDQwLCAweDgwLCAweDFiLCAweDM2XTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBBRVMgYmxvY2sgY2lwaGVyIGFsZ29yaXRobS5cblx0ICAgICAqL1xuXHQgICAgdmFyIEFFUyA9IENfYWxnby5BRVMgPSBCbG9ja0NpcGhlci5leHRlbmQoe1xuXHQgICAgICAgIF9kb1Jlc2V0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIC8vIFNraXAgcmVzZXQgb2YgblJvdW5kcyBoYXMgYmVlbiBzZXQgYmVmb3JlIGFuZCBrZXkgZGlkIG5vdCBjaGFuZ2Vcblx0ICAgICAgICAgICAgaWYgKHRoaXMuX25Sb3VuZHMgJiYgdGhpcy5fa2V5UHJpb3JSZXNldCA9PT0gdGhpcy5fa2V5KSB7XG5cdCAgICAgICAgICAgICAgICByZXR1cm47XG5cdCAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIGtleSA9IHRoaXMuX2tleVByaW9yUmVzZXQgPSB0aGlzLl9rZXk7XG5cdCAgICAgICAgICAgIHZhciBrZXlXb3JkcyA9IGtleS53b3Jkcztcblx0ICAgICAgICAgICAgdmFyIGtleVNpemUgPSBrZXkuc2lnQnl0ZXMgLyA0O1xuXG5cdCAgICAgICAgICAgIC8vIENvbXB1dGUgbnVtYmVyIG9mIHJvdW5kc1xuXHQgICAgICAgICAgICB2YXIgblJvdW5kcyA9IHRoaXMuX25Sb3VuZHMgPSBrZXlTaXplICsgNjtcblxuXHQgICAgICAgICAgICAvLyBDb21wdXRlIG51bWJlciBvZiBrZXkgc2NoZWR1bGUgcm93c1xuXHQgICAgICAgICAgICB2YXIga3NSb3dzID0gKG5Sb3VuZHMgKyAxKSAqIDQ7XG5cblx0ICAgICAgICAgICAgLy8gQ29tcHV0ZSBrZXkgc2NoZWR1bGVcblx0ICAgICAgICAgICAgdmFyIGtleVNjaGVkdWxlID0gdGhpcy5fa2V5U2NoZWR1bGUgPSBbXTtcblx0ICAgICAgICAgICAgZm9yICh2YXIga3NSb3cgPSAwOyBrc1JvdyA8IGtzUm93czsga3NSb3crKykge1xuXHQgICAgICAgICAgICAgICAgaWYgKGtzUm93IDwga2V5U2l6ZSkge1xuXHQgICAgICAgICAgICAgICAgICAgIGtleVNjaGVkdWxlW2tzUm93XSA9IGtleVdvcmRzW2tzUm93XTtcblx0ICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdmFyIHQgPSBrZXlTY2hlZHVsZVtrc1JvdyAtIDFdO1xuXG5cdCAgICAgICAgICAgICAgICAgICAgaWYgKCEoa3NSb3cgJSBrZXlTaXplKSkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICAvLyBSb3Qgd29yZFxuXHQgICAgICAgICAgICAgICAgICAgICAgICB0ID0gKHQgPDwgOCkgfCAodCA+Pj4gMjQpO1xuXG5cdCAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN1YiB3b3JkXG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHQgPSAoU0JPWFt0ID4+PiAyNF0gPDwgMjQpIHwgKFNCT1hbKHQgPj4+IDE2KSAmIDB4ZmZdIDw8IDE2KSB8IChTQk9YWyh0ID4+PiA4KSAmIDB4ZmZdIDw8IDgpIHwgU0JPWFt0ICYgMHhmZl07XG5cblx0ICAgICAgICAgICAgICAgICAgICAgICAgLy8gTWl4IFJjb25cblx0ICAgICAgICAgICAgICAgICAgICAgICAgdCBePSBSQ09OWyhrc1JvdyAvIGtleVNpemUpIHwgMF0gPDwgMjQ7XG5cdCAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChrZXlTaXplID4gNiAmJiBrc1JvdyAlIGtleVNpemUgPT0gNCkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICAvLyBTdWIgd29yZFxuXHQgICAgICAgICAgICAgICAgICAgICAgICB0ID0gKFNCT1hbdCA+Pj4gMjRdIDw8IDI0KSB8IChTQk9YWyh0ID4+PiAxNikgJiAweGZmXSA8PCAxNikgfCAoU0JPWFsodCA+Pj4gOCkgJiAweGZmXSA8PCA4KSB8IFNCT1hbdCAmIDB4ZmZdO1xuXHQgICAgICAgICAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICAgICAgICAgIGtleVNjaGVkdWxlW2tzUm93XSA9IGtleVNjaGVkdWxlW2tzUm93IC0ga2V5U2l6ZV0gXiB0O1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gQ29tcHV0ZSBpbnYga2V5IHNjaGVkdWxlXG5cdCAgICAgICAgICAgIHZhciBpbnZLZXlTY2hlZHVsZSA9IHRoaXMuX2ludktleVNjaGVkdWxlID0gW107XG5cdCAgICAgICAgICAgIGZvciAodmFyIGludktzUm93ID0gMDsgaW52S3NSb3cgPCBrc1Jvd3M7IGludktzUm93KyspIHtcblx0ICAgICAgICAgICAgICAgIHZhciBrc1JvdyA9IGtzUm93cyAtIGludktzUm93O1xuXG5cdCAgICAgICAgICAgICAgICBpZiAoaW52S3NSb3cgJSA0KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdmFyIHQgPSBrZXlTY2hlZHVsZVtrc1Jvd107XG5cdCAgICAgICAgICAgICAgICB9IGVsc2Uge1xuXHQgICAgICAgICAgICAgICAgICAgIHZhciB0ID0ga2V5U2NoZWR1bGVba3NSb3cgLSA0XTtcblx0ICAgICAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICAgICAgaWYgKGludktzUm93IDwgNCB8fCBrc1JvdyA8PSA0KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgaW52S2V5U2NoZWR1bGVbaW52S3NSb3ddID0gdDtcblx0ICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICAgICAgaW52S2V5U2NoZWR1bGVbaW52S3NSb3ddID0gSU5WX1NVQl9NSVhfMFtTQk9YW3QgPj4+IDI0XV0gXiBJTlZfU1VCX01JWF8xW1NCT1hbKHQgPj4+IDE2KSAmIDB4ZmZdXSBeXG5cdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgSU5WX1NVQl9NSVhfMltTQk9YWyh0ID4+PiA4KSAmIDB4ZmZdXSBeIElOVl9TVUJfTUlYXzNbU0JPWFt0ICYgMHhmZl1dO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIGVuY3J5cHRCbG9jazogZnVuY3Rpb24gKE0sIG9mZnNldCkge1xuXHQgICAgICAgICAgICB0aGlzLl9kb0NyeXB0QmxvY2soTSwgb2Zmc2V0LCB0aGlzLl9rZXlTY2hlZHVsZSwgU1VCX01JWF8wLCBTVUJfTUlYXzEsIFNVQl9NSVhfMiwgU1VCX01JWF8zLCBTQk9YKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgZGVjcnlwdEJsb2NrOiBmdW5jdGlvbiAoTSwgb2Zmc2V0KSB7XG5cdCAgICAgICAgICAgIC8vIFN3YXAgMm5kIGFuZCA0dGggcm93c1xuXHQgICAgICAgICAgICB2YXIgdCA9IE1bb2Zmc2V0ICsgMV07XG5cdCAgICAgICAgICAgIE1bb2Zmc2V0ICsgMV0gPSBNW29mZnNldCArIDNdO1xuXHQgICAgICAgICAgICBNW29mZnNldCArIDNdID0gdDtcblxuXHQgICAgICAgICAgICB0aGlzLl9kb0NyeXB0QmxvY2soTSwgb2Zmc2V0LCB0aGlzLl9pbnZLZXlTY2hlZHVsZSwgSU5WX1NVQl9NSVhfMCwgSU5WX1NVQl9NSVhfMSwgSU5WX1NVQl9NSVhfMiwgSU5WX1NVQl9NSVhfMywgSU5WX1NCT1gpO1xuXG5cdCAgICAgICAgICAgIC8vIEludiBzd2FwIDJuZCBhbmQgNHRoIHJvd3Ncblx0ICAgICAgICAgICAgdmFyIHQgPSBNW29mZnNldCArIDFdO1xuXHQgICAgICAgICAgICBNW29mZnNldCArIDFdID0gTVtvZmZzZXQgKyAzXTtcblx0ICAgICAgICAgICAgTVtvZmZzZXQgKyAzXSA9IHQ7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIF9kb0NyeXB0QmxvY2s6IGZ1bmN0aW9uIChNLCBvZmZzZXQsIGtleVNjaGVkdWxlLCBTVUJfTUlYXzAsIFNVQl9NSVhfMSwgU1VCX01JWF8yLCBTVUJfTUlYXzMsIFNCT1gpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRcblx0ICAgICAgICAgICAgdmFyIG5Sb3VuZHMgPSB0aGlzLl9uUm91bmRzO1xuXG5cdCAgICAgICAgICAgIC8vIEdldCBpbnB1dCwgYWRkIHJvdW5kIGtleVxuXHQgICAgICAgICAgICB2YXIgczAgPSBNW29mZnNldF0gICAgIF4ga2V5U2NoZWR1bGVbMF07XG5cdCAgICAgICAgICAgIHZhciBzMSA9IE1bb2Zmc2V0ICsgMV0gXiBrZXlTY2hlZHVsZVsxXTtcblx0ICAgICAgICAgICAgdmFyIHMyID0gTVtvZmZzZXQgKyAyXSBeIGtleVNjaGVkdWxlWzJdO1xuXHQgICAgICAgICAgICB2YXIgczMgPSBNW29mZnNldCArIDNdIF4ga2V5U2NoZWR1bGVbM107XG5cblx0ICAgICAgICAgICAgLy8gS2V5IHNjaGVkdWxlIHJvdyBjb3VudGVyXG5cdCAgICAgICAgICAgIHZhciBrc1JvdyA9IDQ7XG5cblx0ICAgICAgICAgICAgLy8gUm91bmRzXG5cdCAgICAgICAgICAgIGZvciAodmFyIHJvdW5kID0gMTsgcm91bmQgPCBuUm91bmRzOyByb3VuZCsrKSB7XG5cdCAgICAgICAgICAgICAgICAvLyBTaGlmdCByb3dzLCBzdWIgYnl0ZXMsIG1peCBjb2x1bW5zLCBhZGQgcm91bmQga2V5XG5cdCAgICAgICAgICAgICAgICB2YXIgdDAgPSBTVUJfTUlYXzBbczAgPj4+IDI0XSBeIFNVQl9NSVhfMVsoczEgPj4+IDE2KSAmIDB4ZmZdIF4gU1VCX01JWF8yWyhzMiA+Pj4gOCkgJiAweGZmXSBeIFNVQl9NSVhfM1tzMyAmIDB4ZmZdIF4ga2V5U2NoZWR1bGVba3NSb3crK107XG5cdCAgICAgICAgICAgICAgICB2YXIgdDEgPSBTVUJfTUlYXzBbczEgPj4+IDI0XSBeIFNVQl9NSVhfMVsoczIgPj4+IDE2KSAmIDB4ZmZdIF4gU1VCX01JWF8yWyhzMyA+Pj4gOCkgJiAweGZmXSBeIFNVQl9NSVhfM1tzMCAmIDB4ZmZdIF4ga2V5U2NoZWR1bGVba3NSb3crK107XG5cdCAgICAgICAgICAgICAgICB2YXIgdDIgPSBTVUJfTUlYXzBbczIgPj4+IDI0XSBeIFNVQl9NSVhfMVsoczMgPj4+IDE2KSAmIDB4ZmZdIF4gU1VCX01JWF8yWyhzMCA+Pj4gOCkgJiAweGZmXSBeIFNVQl9NSVhfM1tzMSAmIDB4ZmZdIF4ga2V5U2NoZWR1bGVba3NSb3crK107XG5cdCAgICAgICAgICAgICAgICB2YXIgdDMgPSBTVUJfTUlYXzBbczMgPj4+IDI0XSBeIFNVQl9NSVhfMVsoczAgPj4+IDE2KSAmIDB4ZmZdIF4gU1VCX01JWF8yWyhzMSA+Pj4gOCkgJiAweGZmXSBeIFNVQl9NSVhfM1tzMiAmIDB4ZmZdIF4ga2V5U2NoZWR1bGVba3NSb3crK107XG5cblx0ICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSBzdGF0ZVxuXHQgICAgICAgICAgICAgICAgczAgPSB0MDtcblx0ICAgICAgICAgICAgICAgIHMxID0gdDE7XG5cdCAgICAgICAgICAgICAgICBzMiA9IHQyO1xuXHQgICAgICAgICAgICAgICAgczMgPSB0Mztcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIFNoaWZ0IHJvd3MsIHN1YiBieXRlcywgYWRkIHJvdW5kIGtleVxuXHQgICAgICAgICAgICB2YXIgdDAgPSAoKFNCT1hbczAgPj4+IDI0XSA8PCAyNCkgfCAoU0JPWFsoczEgPj4+IDE2KSAmIDB4ZmZdIDw8IDE2KSB8IChTQk9YWyhzMiA+Pj4gOCkgJiAweGZmXSA8PCA4KSB8IFNCT1hbczMgJiAweGZmXSkgXiBrZXlTY2hlZHVsZVtrc1JvdysrXTtcblx0ICAgICAgICAgICAgdmFyIHQxID0gKChTQk9YW3MxID4+PiAyNF0gPDwgMjQpIHwgKFNCT1hbKHMyID4+PiAxNikgJiAweGZmXSA8PCAxNikgfCAoU0JPWFsoczMgPj4+IDgpICYgMHhmZl0gPDwgOCkgfCBTQk9YW3MwICYgMHhmZl0pIF4ga2V5U2NoZWR1bGVba3NSb3crK107XG5cdCAgICAgICAgICAgIHZhciB0MiA9ICgoU0JPWFtzMiA+Pj4gMjRdIDw8IDI0KSB8IChTQk9YWyhzMyA+Pj4gMTYpICYgMHhmZl0gPDwgMTYpIHwgKFNCT1hbKHMwID4+PiA4KSAmIDB4ZmZdIDw8IDgpIHwgU0JPWFtzMSAmIDB4ZmZdKSBeIGtleVNjaGVkdWxlW2tzUm93KytdO1xuXHQgICAgICAgICAgICB2YXIgdDMgPSAoKFNCT1hbczMgPj4+IDI0XSA8PCAyNCkgfCAoU0JPWFsoczAgPj4+IDE2KSAmIDB4ZmZdIDw8IDE2KSB8IChTQk9YWyhzMSA+Pj4gOCkgJiAweGZmXSA8PCA4KSB8IFNCT1hbczIgJiAweGZmXSkgXiBrZXlTY2hlZHVsZVtrc1JvdysrXTtcblxuXHQgICAgICAgICAgICAvLyBTZXQgb3V0cHV0XG5cdCAgICAgICAgICAgIE1bb2Zmc2V0XSAgICAgPSB0MDtcblx0ICAgICAgICAgICAgTVtvZmZzZXQgKyAxXSA9IHQxO1xuXHQgICAgICAgICAgICBNW29mZnNldCArIDJdID0gdDI7XG5cdCAgICAgICAgICAgIE1bb2Zmc2V0ICsgM10gPSB0Mztcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAga2V5U2l6ZTogMjU2LzMyXG5cdCAgICB9KTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG9ydGN1dCBmdW5jdGlvbnMgdG8gdGhlIGNpcGhlcidzIG9iamVjdCBpbnRlcmZhY2UuXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiAgICAgdmFyIGNpcGhlcnRleHQgPSBDcnlwdG9KUy5BRVMuZW5jcnlwdChtZXNzYWdlLCBrZXksIGNmZyk7XG5cdCAgICAgKiAgICAgdmFyIHBsYWludGV4dCAgPSBDcnlwdG9KUy5BRVMuZGVjcnlwdChjaXBoZXJ0ZXh0LCBrZXksIGNmZyk7XG5cdCAgICAgKi9cblx0ICAgIEMuQUVTID0gQmxvY2tDaXBoZXIuX2NyZWF0ZUhlbHBlcihBRVMpO1xuXHR9KCkpO1xuXG5cblx0cmV0dXJuIENyeXB0b0pTLkFFUztcblxufSkpOyIsIjsoZnVuY3Rpb24gKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYgKHR5cGVvZiBleHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoXCIuL2NvcmVcIikpO1xuXHR9XG5cdGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKFtcIi4vY29yZVwiXSwgZmFjdG9yeSk7XG5cdH1cblx0ZWxzZSB7XG5cdFx0Ly8gR2xvYmFsIChicm93c2VyKVxuXHRcdGZhY3Rvcnkocm9vdC5DcnlwdG9KUyk7XG5cdH1cbn0odGhpcywgZnVuY3Rpb24gKENyeXB0b0pTKSB7XG5cblx0LyoqXG5cdCAqIENpcGhlciBjb3JlIGNvbXBvbmVudHMuXG5cdCAqL1xuXHRDcnlwdG9KUy5saWIuQ2lwaGVyIHx8IChmdW5jdGlvbiAodW5kZWZpbmVkKSB7XG5cdCAgICAvLyBTaG9ydGN1dHNcblx0ICAgIHZhciBDID0gQ3J5cHRvSlM7XG5cdCAgICB2YXIgQ19saWIgPSBDLmxpYjtcblx0ICAgIHZhciBCYXNlID0gQ19saWIuQmFzZTtcblx0ICAgIHZhciBXb3JkQXJyYXkgPSBDX2xpYi5Xb3JkQXJyYXk7XG5cdCAgICB2YXIgQnVmZmVyZWRCbG9ja0FsZ29yaXRobSA9IENfbGliLkJ1ZmZlcmVkQmxvY2tBbGdvcml0aG07XG5cdCAgICB2YXIgQ19lbmMgPSBDLmVuYztcblx0ICAgIHZhciBVdGY4ID0gQ19lbmMuVXRmODtcblx0ICAgIHZhciBCYXNlNjQgPSBDX2VuYy5CYXNlNjQ7XG5cdCAgICB2YXIgQ19hbGdvID0gQy5hbGdvO1xuXHQgICAgdmFyIEV2cEtERiA9IENfYWxnby5FdnBLREY7XG5cblx0ICAgIC8qKlxuXHQgICAgICogQWJzdHJhY3QgYmFzZSBjaXBoZXIgdGVtcGxhdGUuXG5cdCAgICAgKlxuXHQgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IGtleVNpemUgVGhpcyBjaXBoZXIncyBrZXkgc2l6ZS4gRGVmYXVsdDogNCAoMTI4IGJpdHMpXG5cdCAgICAgKiBAcHJvcGVydHkge251bWJlcn0gaXZTaXplIFRoaXMgY2lwaGVyJ3MgSVYgc2l6ZS4gRGVmYXVsdDogNCAoMTI4IGJpdHMpXG5cdCAgICAgKiBAcHJvcGVydHkge251bWJlcn0gX0VOQ19YRk9STV9NT0RFIEEgY29uc3RhbnQgcmVwcmVzZW50aW5nIGVuY3J5cHRpb24gbW9kZS5cblx0ICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBfREVDX1hGT1JNX01PREUgQSBjb25zdGFudCByZXByZXNlbnRpbmcgZGVjcnlwdGlvbiBtb2RlLlxuXHQgICAgICovXG5cdCAgICB2YXIgQ2lwaGVyID0gQ19saWIuQ2lwaGVyID0gQnVmZmVyZWRCbG9ja0FsZ29yaXRobS5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbmZpZ3VyYXRpb24gb3B0aW9ucy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwcm9wZXJ0eSB7V29yZEFycmF5fSBpdiBUaGUgSVYgdG8gdXNlIGZvciB0aGlzIG9wZXJhdGlvbi5cblx0ICAgICAgICAgKi9cblx0ICAgICAgICBjZmc6IEJhc2UuZXh0ZW5kKCksXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDcmVhdGVzIHRoaXMgY2lwaGVyIGluIGVuY3J5cHRpb24gbW9kZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fSBrZXkgVGhlIGtleS5cblx0ICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gY2ZnIChPcHRpb25hbCkgVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byB1c2UgZm9yIHRoaXMgb3BlcmF0aW9uLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7Q2lwaGVyfSBBIGNpcGhlciBpbnN0YW5jZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGNpcGhlciA9IENyeXB0b0pTLmFsZ28uQUVTLmNyZWF0ZUVuY3J5cHRvcihrZXlXb3JkQXJyYXksIHsgaXY6IGl2V29yZEFycmF5IH0pO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNyZWF0ZUVuY3J5cHRvcjogZnVuY3Rpb24gKGtleSwgY2ZnKSB7XG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZSh0aGlzLl9FTkNfWEZPUk1fTU9ERSwga2V5LCBjZmcpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDcmVhdGVzIHRoaXMgY2lwaGVyIGluIGRlY3J5cHRpb24gbW9kZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fSBrZXkgVGhlIGtleS5cblx0ICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gY2ZnIChPcHRpb25hbCkgVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byB1c2UgZm9yIHRoaXMgb3BlcmF0aW9uLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7Q2lwaGVyfSBBIGNpcGhlciBpbnN0YW5jZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGNpcGhlciA9IENyeXB0b0pTLmFsZ28uQUVTLmNyZWF0ZURlY3J5cHRvcihrZXlXb3JkQXJyYXksIHsgaXY6IGl2V29yZEFycmF5IH0pO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNyZWF0ZURlY3J5cHRvcjogZnVuY3Rpb24gKGtleSwgY2ZnKSB7XG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzLmNyZWF0ZSh0aGlzLl9ERUNfWEZPUk1fTU9ERSwga2V5LCBjZmcpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBJbml0aWFsaXplcyBhIG5ld2x5IGNyZWF0ZWQgY2lwaGVyLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtudW1iZXJ9IHhmb3JtTW9kZSBFaXRoZXIgdGhlIGVuY3J5cHRpb24gb3IgZGVjcnlwdGlvbiB0cmFuc29ybWF0aW9uIG1vZGUgY29uc3RhbnQuXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl9IGtleSBUaGUga2V5LlxuXHQgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjZmcgKE9wdGlvbmFsKSBUaGUgY29uZmlndXJhdGlvbiBvcHRpb25zIHRvIHVzZSBmb3IgdGhpcyBvcGVyYXRpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBjaXBoZXIgPSBDcnlwdG9KUy5hbGdvLkFFUy5jcmVhdGUoQ3J5cHRvSlMuYWxnby5BRVMuX0VOQ19YRk9STV9NT0RFLCBrZXlXb3JkQXJyYXksIHsgaXY6IGl2V29yZEFycmF5IH0pO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGluaXQ6IGZ1bmN0aW9uICh4Zm9ybU1vZGUsIGtleSwgY2ZnKSB7XG5cdCAgICAgICAgICAgIC8vIEFwcGx5IGNvbmZpZyBkZWZhdWx0c1xuXHQgICAgICAgICAgICB0aGlzLmNmZyA9IHRoaXMuY2ZnLmV4dGVuZChjZmcpO1xuXG5cdCAgICAgICAgICAgIC8vIFN0b3JlIHRyYW5zZm9ybSBtb2RlIGFuZCBrZXlcblx0ICAgICAgICAgICAgdGhpcy5feGZvcm1Nb2RlID0geGZvcm1Nb2RlO1xuXHQgICAgICAgICAgICB0aGlzLl9rZXkgPSBrZXk7XG5cblx0ICAgICAgICAgICAgLy8gU2V0IGluaXRpYWwgdmFsdWVzXG5cdCAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogUmVzZXRzIHRoaXMgY2lwaGVyIHRvIGl0cyBpbml0aWFsIHN0YXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBjaXBoZXIucmVzZXQoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBSZXNldCBkYXRhIGJ1ZmZlclxuXHQgICAgICAgICAgICBCdWZmZXJlZEJsb2NrQWxnb3JpdGhtLnJlc2V0LmNhbGwodGhpcyk7XG5cblx0ICAgICAgICAgICAgLy8gUGVyZm9ybSBjb25jcmV0ZS1jaXBoZXIgbG9naWNcblx0ICAgICAgICAgICAgdGhpcy5fZG9SZXNldCgpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBBZGRzIGRhdGEgdG8gYmUgZW5jcnlwdGVkIG9yIGRlY3J5cHRlZC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30gZGF0YVVwZGF0ZSBUaGUgZGF0YSB0byBlbmNyeXB0IG9yIGRlY3J5cHQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBkYXRhIGFmdGVyIHByb2Nlc3NpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBlbmNyeXB0ZWQgPSBjaXBoZXIucHJvY2VzcygnZGF0YScpO1xuXHQgICAgICAgICAqICAgICB2YXIgZW5jcnlwdGVkID0gY2lwaGVyLnByb2Nlc3Mod29yZEFycmF5KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBwcm9jZXNzOiBmdW5jdGlvbiAoZGF0YVVwZGF0ZSkge1xuXHQgICAgICAgICAgICAvLyBBcHBlbmRcblx0ICAgICAgICAgICAgdGhpcy5fYXBwZW5kKGRhdGFVcGRhdGUpO1xuXG5cdCAgICAgICAgICAgIC8vIFByb2Nlc3MgYXZhaWxhYmxlIGJsb2Nrc1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5fcHJvY2VzcygpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBGaW5hbGl6ZXMgdGhlIGVuY3J5cHRpb24gb3IgZGVjcnlwdGlvbiBwcm9jZXNzLlxuXHQgICAgICAgICAqIE5vdGUgdGhhdCB0aGUgZmluYWxpemUgb3BlcmF0aW9uIGlzIGVmZmVjdGl2ZWx5IGEgZGVzdHJ1Y3RpdmUsIHJlYWQtb25jZSBvcGVyYXRpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IGRhdGFVcGRhdGUgVGhlIGZpbmFsIGRhdGEgdG8gZW5jcnlwdCBvciBkZWNyeXB0LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgZGF0YSBhZnRlciBmaW5hbCBwcm9jZXNzaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgZW5jcnlwdGVkID0gY2lwaGVyLmZpbmFsaXplKCk7XG5cdCAgICAgICAgICogICAgIHZhciBlbmNyeXB0ZWQgPSBjaXBoZXIuZmluYWxpemUoJ2RhdGEnKTtcblx0ICAgICAgICAgKiAgICAgdmFyIGVuY3J5cHRlZCA9IGNpcGhlci5maW5hbGl6ZSh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGZpbmFsaXplOiBmdW5jdGlvbiAoZGF0YVVwZGF0ZSkge1xuXHQgICAgICAgICAgICAvLyBGaW5hbCBkYXRhIHVwZGF0ZVxuXHQgICAgICAgICAgICBpZiAoZGF0YVVwZGF0ZSkge1xuXHQgICAgICAgICAgICAgICAgdGhpcy5fYXBwZW5kKGRhdGFVcGRhdGUpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gUGVyZm9ybSBjb25jcmV0ZS1jaXBoZXIgbG9naWNcblx0ICAgICAgICAgICAgdmFyIGZpbmFsUHJvY2Vzc2VkRGF0YSA9IHRoaXMuX2RvRmluYWxpemUoKTtcblxuXHQgICAgICAgICAgICByZXR1cm4gZmluYWxQcm9jZXNzZWREYXRhO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICBrZXlTaXplOiAxMjgvMzIsXG5cblx0ICAgICAgICBpdlNpemU6IDEyOC8zMixcblxuXHQgICAgICAgIF9FTkNfWEZPUk1fTU9ERTogMSxcblxuXHQgICAgICAgIF9ERUNfWEZPUk1fTU9ERTogMixcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENyZWF0ZXMgc2hvcnRjdXQgZnVuY3Rpb25zIHRvIGEgY2lwaGVyJ3Mgb2JqZWN0IGludGVyZmFjZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7Q2lwaGVyfSBjaXBoZXIgVGhlIGNpcGhlciB0byBjcmVhdGUgYSBoZWxwZXIgZm9yLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7T2JqZWN0fSBBbiBvYmplY3Qgd2l0aCBlbmNyeXB0IGFuZCBkZWNyeXB0IHNob3J0Y3V0IGZ1bmN0aW9ucy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIEFFUyA9IENyeXB0b0pTLmxpYi5DaXBoZXIuX2NyZWF0ZUhlbHBlcihDcnlwdG9KUy5hbGdvLkFFUyk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgX2NyZWF0ZUhlbHBlcjogKGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgZnVuY3Rpb24gc2VsZWN0Q2lwaGVyU3RyYXRlZ3koa2V5KSB7XG5cdCAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGtleSA9PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICAgICAgICAgIHJldHVybiBQYXNzd29yZEJhc2VkQ2lwaGVyO1xuXHQgICAgICAgICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICAgICAgICAgICAgICByZXR1cm4gU2VyaWFsaXphYmxlQ2lwaGVyO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIChjaXBoZXIpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiB7XG5cdCAgICAgICAgICAgICAgICAgICAgZW5jcnlwdDogZnVuY3Rpb24gKG1lc3NhZ2UsIGtleSwgY2ZnKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBzZWxlY3RDaXBoZXJTdHJhdGVneShrZXkpLmVuY3J5cHQoY2lwaGVyLCBtZXNzYWdlLCBrZXksIGNmZyk7XG5cdCAgICAgICAgICAgICAgICAgICAgfSxcblxuXHQgICAgICAgICAgICAgICAgICAgIGRlY3J5cHQ6IGZ1bmN0aW9uIChjaXBoZXJ0ZXh0LCBrZXksIGNmZykge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gc2VsZWN0Q2lwaGVyU3RyYXRlZ3koa2V5KS5kZWNyeXB0KGNpcGhlciwgY2lwaGVydGV4dCwga2V5LCBjZmcpO1xuXHQgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgICAgIH07XG5cdCAgICAgICAgICAgIH07XG5cdCAgICAgICAgfSgpKVxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogQWJzdHJhY3QgYmFzZSBzdHJlYW0gY2lwaGVyIHRlbXBsYXRlLlxuXHQgICAgICpcblx0ICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBibG9ja1NpemUgVGhlIG51bWJlciBvZiAzMi1iaXQgd29yZHMgdGhpcyBjaXBoZXIgb3BlcmF0ZXMgb24uIERlZmF1bHQ6IDEgKDMyIGJpdHMpXG5cdCAgICAgKi9cblx0ICAgIHZhciBTdHJlYW1DaXBoZXIgPSBDX2xpYi5TdHJlYW1DaXBoZXIgPSBDaXBoZXIuZXh0ZW5kKHtcblx0ICAgICAgICBfZG9GaW5hbGl6ZTogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBQcm9jZXNzIHBhcnRpYWwgYmxvY2tzXG5cdCAgICAgICAgICAgIHZhciBmaW5hbFByb2Nlc3NlZEJsb2NrcyA9IHRoaXMuX3Byb2Nlc3MoISEnZmx1c2gnKTtcblxuXHQgICAgICAgICAgICByZXR1cm4gZmluYWxQcm9jZXNzZWRCbG9ja3M7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIGJsb2NrU2l6ZTogMVxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogTW9kZSBuYW1lc3BhY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBDX21vZGUgPSBDLm1vZGUgPSB7fTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBBYnN0cmFjdCBiYXNlIGJsb2NrIGNpcGhlciBtb2RlIHRlbXBsYXRlLlxuXHQgICAgICovXG5cdCAgICB2YXIgQmxvY2tDaXBoZXJNb2RlID0gQ19saWIuQmxvY2tDaXBoZXJNb2RlID0gQmFzZS5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENyZWF0ZXMgdGhpcyBtb2RlIGZvciBlbmNyeXB0aW9uLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtDaXBoZXJ9IGNpcGhlciBBIGJsb2NrIGNpcGhlciBpbnN0YW5jZS5cblx0ICAgICAgICAgKiBAcGFyYW0ge0FycmF5fSBpdiBUaGUgSVYgd29yZHMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBtb2RlID0gQ3J5cHRvSlMubW9kZS5DQkMuY3JlYXRlRW5jcnlwdG9yKGNpcGhlciwgaXYud29yZHMpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNyZWF0ZUVuY3J5cHRvcjogZnVuY3Rpb24gKGNpcGhlciwgaXYpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIHRoaXMuRW5jcnlwdG9yLmNyZWF0ZShjaXBoZXIsIGl2KTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyB0aGlzIG1vZGUgZm9yIGRlY3J5cHRpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0NpcGhlcn0gY2lwaGVyIEEgYmxvY2sgY2lwaGVyIGluc3RhbmNlLlxuXHQgICAgICAgICAqIEBwYXJhbSB7QXJyYXl9IGl2IFRoZSBJViB3b3Jkcy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIG1vZGUgPSBDcnlwdG9KUy5tb2RlLkNCQy5jcmVhdGVEZWNyeXB0b3IoY2lwaGVyLCBpdi53b3Jkcyk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgY3JlYXRlRGVjcnlwdG9yOiBmdW5jdGlvbiAoY2lwaGVyLCBpdikge1xuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5EZWNyeXB0b3IuY3JlYXRlKGNpcGhlciwgaXYpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBJbml0aWFsaXplcyBhIG5ld2x5IGNyZWF0ZWQgbW9kZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7Q2lwaGVyfSBjaXBoZXIgQSBibG9jayBjaXBoZXIgaW5zdGFuY2UuXG5cdCAgICAgICAgICogQHBhcmFtIHtBcnJheX0gaXYgVGhlIElWIHdvcmRzLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgbW9kZSA9IENyeXB0b0pTLm1vZGUuQ0JDLkVuY3J5cHRvci5jcmVhdGUoY2lwaGVyLCBpdi53b3Jkcyk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgaW5pdDogZnVuY3Rpb24gKGNpcGhlciwgaXYpIHtcblx0ICAgICAgICAgICAgdGhpcy5fY2lwaGVyID0gY2lwaGVyO1xuXHQgICAgICAgICAgICB0aGlzLl9pdiA9IGl2O1xuXHQgICAgICAgIH1cblx0ICAgIH0pO1xuXG5cdCAgICAvKipcblx0ICAgICAqIENpcGhlciBCbG9jayBDaGFpbmluZyBtb2RlLlxuXHQgICAgICovXG5cdCAgICB2YXIgQ0JDID0gQ19tb2RlLkNCQyA9IChmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQWJzdHJhY3QgYmFzZSBDQkMgbW9kZS5cblx0ICAgICAgICAgKi9cblx0ICAgICAgICB2YXIgQ0JDID0gQmxvY2tDaXBoZXJNb2RlLmV4dGVuZCgpO1xuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ0JDIGVuY3J5cHRvci5cblx0ICAgICAgICAgKi9cblx0ICAgICAgICBDQkMuRW5jcnlwdG9yID0gQ0JDLmV4dGVuZCh7XG5cdCAgICAgICAgICAgIC8qKlxuXHQgICAgICAgICAgICAgKiBQcm9jZXNzZXMgdGhlIGRhdGEgYmxvY2sgYXQgb2Zmc2V0LlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAcGFyYW0ge0FycmF5fSB3b3JkcyBUaGUgZGF0YSB3b3JkcyB0byBvcGVyYXRlIG9uLlxuXHQgICAgICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IFRoZSBvZmZzZXQgd2hlcmUgdGhlIGJsb2NrIHN0YXJ0cy5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogICAgIG1vZGUucHJvY2Vzc0Jsb2NrKGRhdGEud29yZHMsIG9mZnNldCk7XG5cdCAgICAgICAgICAgICAqL1xuXHQgICAgICAgICAgICBwcm9jZXNzQmxvY2s6IGZ1bmN0aW9uICh3b3Jkcywgb2Zmc2V0KSB7XG5cdCAgICAgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgICAgIHZhciBjaXBoZXIgPSB0aGlzLl9jaXBoZXI7XG5cdCAgICAgICAgICAgICAgICB2YXIgYmxvY2tTaXplID0gY2lwaGVyLmJsb2NrU2l6ZTtcblxuXHQgICAgICAgICAgICAgICAgLy8gWE9SIGFuZCBlbmNyeXB0XG5cdCAgICAgICAgICAgICAgICB4b3JCbG9jay5jYWxsKHRoaXMsIHdvcmRzLCBvZmZzZXQsIGJsb2NrU2l6ZSk7XG5cdCAgICAgICAgICAgICAgICBjaXBoZXIuZW5jcnlwdEJsb2NrKHdvcmRzLCBvZmZzZXQpO1xuXG5cdCAgICAgICAgICAgICAgICAvLyBSZW1lbWJlciB0aGlzIGJsb2NrIHRvIHVzZSB3aXRoIG5leHQgYmxvY2tcblx0ICAgICAgICAgICAgICAgIHRoaXMuX3ByZXZCbG9jayA9IHdvcmRzLnNsaWNlKG9mZnNldCwgb2Zmc2V0ICsgYmxvY2tTaXplKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ0JDIGRlY3J5cHRvci5cblx0ICAgICAgICAgKi9cblx0ICAgICAgICBDQkMuRGVjcnlwdG9yID0gQ0JDLmV4dGVuZCh7XG5cdCAgICAgICAgICAgIC8qKlxuXHQgICAgICAgICAgICAgKiBQcm9jZXNzZXMgdGhlIGRhdGEgYmxvY2sgYXQgb2Zmc2V0LlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAcGFyYW0ge0FycmF5fSB3b3JkcyBUaGUgZGF0YSB3b3JkcyB0byBvcGVyYXRlIG9uLlxuXHQgICAgICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gb2Zmc2V0IFRoZSBvZmZzZXQgd2hlcmUgdGhlIGJsb2NrIHN0YXJ0cy5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogICAgIG1vZGUucHJvY2Vzc0Jsb2NrKGRhdGEud29yZHMsIG9mZnNldCk7XG5cdCAgICAgICAgICAgICAqL1xuXHQgICAgICAgICAgICBwcm9jZXNzQmxvY2s6IGZ1bmN0aW9uICh3b3Jkcywgb2Zmc2V0KSB7XG5cdCAgICAgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgICAgIHZhciBjaXBoZXIgPSB0aGlzLl9jaXBoZXI7XG5cdCAgICAgICAgICAgICAgICB2YXIgYmxvY2tTaXplID0gY2lwaGVyLmJsb2NrU2l6ZTtcblxuXHQgICAgICAgICAgICAgICAgLy8gUmVtZW1iZXIgdGhpcyBibG9jayB0byB1c2Ugd2l0aCBuZXh0IGJsb2NrXG5cdCAgICAgICAgICAgICAgICB2YXIgdGhpc0Jsb2NrID0gd29yZHMuc2xpY2Uob2Zmc2V0LCBvZmZzZXQgKyBibG9ja1NpemUpO1xuXG5cdCAgICAgICAgICAgICAgICAvLyBEZWNyeXB0IGFuZCBYT1Jcblx0ICAgICAgICAgICAgICAgIGNpcGhlci5kZWNyeXB0QmxvY2sod29yZHMsIG9mZnNldCk7XG5cdCAgICAgICAgICAgICAgICB4b3JCbG9jay5jYWxsKHRoaXMsIHdvcmRzLCBvZmZzZXQsIGJsb2NrU2l6ZSk7XG5cblx0ICAgICAgICAgICAgICAgIC8vIFRoaXMgYmxvY2sgYmVjb21lcyB0aGUgcHJldmlvdXMgYmxvY2tcblx0ICAgICAgICAgICAgICAgIHRoaXMuX3ByZXZCbG9jayA9IHRoaXNCbG9jaztcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0pO1xuXG5cdCAgICAgICAgZnVuY3Rpb24geG9yQmxvY2sod29yZHMsIG9mZnNldCwgYmxvY2tTaXplKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0XG5cdCAgICAgICAgICAgIHZhciBpdiA9IHRoaXMuX2l2O1xuXG5cdCAgICAgICAgICAgIC8vIENob29zZSBtaXhpbmcgYmxvY2tcblx0ICAgICAgICAgICAgaWYgKGl2KSB7XG5cdCAgICAgICAgICAgICAgICB2YXIgYmxvY2sgPSBpdjtcblxuXHQgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIElWIGZvciBzdWJzZXF1ZW50IGJsb2Nrc1xuXHQgICAgICAgICAgICAgICAgdGhpcy5faXYgPSB1bmRlZmluZWQ7XG5cdCAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICB2YXIgYmxvY2sgPSB0aGlzLl9wcmV2QmxvY2s7XG5cdCAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICAvLyBYT1IgYmxvY2tzXG5cdCAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYmxvY2tTaXplOyBpKyspIHtcblx0ICAgICAgICAgICAgICAgIHdvcmRzW29mZnNldCArIGldIF49IGJsb2NrW2ldO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfVxuXG5cdCAgICAgICAgcmV0dXJuIENCQztcblx0ICAgIH0oKSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogUGFkZGluZyBuYW1lc3BhY2UuXG5cdCAgICAgKi9cblx0ICAgIHZhciBDX3BhZCA9IEMucGFkID0ge307XG5cblx0ICAgIC8qKlxuXHQgICAgICogUEtDUyAjNS83IHBhZGRpbmcgc3RyYXRlZ3kuXG5cdCAgICAgKi9cblx0ICAgIHZhciBQa2NzNyA9IENfcGFkLlBrY3M3ID0ge1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFBhZHMgZGF0YSB1c2luZyB0aGUgYWxnb3JpdGhtIGRlZmluZWQgaW4gUEtDUyAjNS83LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl9IGRhdGEgVGhlIGRhdGEgdG8gcGFkLlxuXHQgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBibG9ja1NpemUgVGhlIG11bHRpcGxlIHRoYXQgdGhlIGRhdGEgc2hvdWxkIGJlIHBhZGRlZCB0by5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgQ3J5cHRvSlMucGFkLlBrY3M3LnBhZCh3b3JkQXJyYXksIDQpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHBhZDogZnVuY3Rpb24gKGRhdGEsIGJsb2NrU2l6ZSkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dFxuXHQgICAgICAgICAgICB2YXIgYmxvY2tTaXplQnl0ZXMgPSBibG9ja1NpemUgKiA0O1xuXG5cdCAgICAgICAgICAgIC8vIENvdW50IHBhZGRpbmcgYnl0ZXNcblx0ICAgICAgICAgICAgdmFyIG5QYWRkaW5nQnl0ZXMgPSBibG9ja1NpemVCeXRlcyAtIGRhdGEuc2lnQnl0ZXMgJSBibG9ja1NpemVCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDcmVhdGUgcGFkZGluZyB3b3JkXG5cdCAgICAgICAgICAgIHZhciBwYWRkaW5nV29yZCA9IChuUGFkZGluZ0J5dGVzIDw8IDI0KSB8IChuUGFkZGluZ0J5dGVzIDw8IDE2KSB8IChuUGFkZGluZ0J5dGVzIDw8IDgpIHwgblBhZGRpbmdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDcmVhdGUgcGFkZGluZ1xuXHQgICAgICAgICAgICB2YXIgcGFkZGluZ1dvcmRzID0gW107XG5cdCAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgblBhZGRpbmdCeXRlczsgaSArPSA0KSB7XG5cdCAgICAgICAgICAgICAgICBwYWRkaW5nV29yZHMucHVzaChwYWRkaW5nV29yZCk7XG5cdCAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgdmFyIHBhZGRpbmcgPSBXb3JkQXJyYXkuY3JlYXRlKHBhZGRpbmdXb3JkcywgblBhZGRpbmdCeXRlcyk7XG5cblx0ICAgICAgICAgICAgLy8gQWRkIHBhZGRpbmdcblx0ICAgICAgICAgICAgZGF0YS5jb25jYXQocGFkZGluZyk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFVucGFkcyBkYXRhIHRoYXQgaGFkIGJlZW4gcGFkZGVkIHVzaW5nIHRoZSBhbGdvcml0aG0gZGVmaW5lZCBpbiBQS0NTICM1LzcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheX0gZGF0YSBUaGUgZGF0YSB0byB1bnBhZC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgQ3J5cHRvSlMucGFkLlBrY3M3LnVucGFkKHdvcmRBcnJheSk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdW5wYWQ6IGZ1bmN0aW9uIChkYXRhKSB7XG5cdCAgICAgICAgICAgIC8vIEdldCBudW1iZXIgb2YgcGFkZGluZyBieXRlcyBmcm9tIGxhc3QgYnl0ZVxuXHQgICAgICAgICAgICB2YXIgblBhZGRpbmdCeXRlcyA9IGRhdGEud29yZHNbKGRhdGEuc2lnQnl0ZXMgLSAxKSA+Pj4gMl0gJiAweGZmO1xuXG5cdCAgICAgICAgICAgIC8vIFJlbW92ZSBwYWRkaW5nXG5cdCAgICAgICAgICAgIGRhdGEuc2lnQnl0ZXMgLT0gblBhZGRpbmdCeXRlcztcblx0ICAgICAgICB9XG5cdCAgICB9O1xuXG5cdCAgICAvKipcblx0ICAgICAqIEFic3RyYWN0IGJhc2UgYmxvY2sgY2lwaGVyIHRlbXBsYXRlLlxuXHQgICAgICpcblx0ICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBibG9ja1NpemUgVGhlIG51bWJlciBvZiAzMi1iaXQgd29yZHMgdGhpcyBjaXBoZXIgb3BlcmF0ZXMgb24uIERlZmF1bHQ6IDQgKDEyOCBiaXRzKVxuXHQgICAgICovXG5cdCAgICB2YXIgQmxvY2tDaXBoZXIgPSBDX2xpYi5CbG9ja0NpcGhlciA9IENpcGhlci5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbmZpZ3VyYXRpb24gb3B0aW9ucy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwcm9wZXJ0eSB7TW9kZX0gbW9kZSBUaGUgYmxvY2sgbW9kZSB0byB1c2UuIERlZmF1bHQ6IENCQ1xuXHQgICAgICAgICAqIEBwcm9wZXJ0eSB7UGFkZGluZ30gcGFkZGluZyBUaGUgcGFkZGluZyBzdHJhdGVneSB0byB1c2UuIERlZmF1bHQ6IFBrY3M3XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgY2ZnOiBDaXBoZXIuY2ZnLmV4dGVuZCh7XG5cdCAgICAgICAgICAgIG1vZGU6IENCQyxcblx0ICAgICAgICAgICAgcGFkZGluZzogUGtjczdcblx0ICAgICAgICB9KSxcblxuXHQgICAgICAgIHJlc2V0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIC8vIFJlc2V0IGNpcGhlclxuXHQgICAgICAgICAgICBDaXBoZXIucmVzZXQuY2FsbCh0aGlzKTtcblxuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIGNmZyA9IHRoaXMuY2ZnO1xuXHQgICAgICAgICAgICB2YXIgaXYgPSBjZmcuaXY7XG5cdCAgICAgICAgICAgIHZhciBtb2RlID0gY2ZnLm1vZGU7XG5cblx0ICAgICAgICAgICAgLy8gUmVzZXQgYmxvY2sgbW9kZVxuXHQgICAgICAgICAgICBpZiAodGhpcy5feGZvcm1Nb2RlID09IHRoaXMuX0VOQ19YRk9STV9NT0RFKSB7XG5cdCAgICAgICAgICAgICAgICB2YXIgbW9kZUNyZWF0b3IgPSBtb2RlLmNyZWF0ZUVuY3J5cHRvcjtcblx0ICAgICAgICAgICAgfSBlbHNlIC8qIGlmICh0aGlzLl94Zm9ybU1vZGUgPT0gdGhpcy5fREVDX1hGT1JNX01PREUpICovIHtcblx0ICAgICAgICAgICAgICAgIHZhciBtb2RlQ3JlYXRvciA9IG1vZGUuY3JlYXRlRGVjcnlwdG9yO1xuXG5cdCAgICAgICAgICAgICAgICAvLyBLZWVwIGF0IGxlYXN0IG9uZSBibG9jayBpbiB0aGUgYnVmZmVyIGZvciB1bnBhZGRpbmdcblx0ICAgICAgICAgICAgICAgIHRoaXMuX21pbkJ1ZmZlclNpemUgPSAxO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIHRoaXMuX21vZGUgPSBtb2RlQ3JlYXRvci5jYWxsKG1vZGUsIHRoaXMsIGl2ICYmIGl2LndvcmRzKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgX2RvUHJvY2Vzc0Jsb2NrOiBmdW5jdGlvbiAod29yZHMsIG9mZnNldCkge1xuXHQgICAgICAgICAgICB0aGlzLl9tb2RlLnByb2Nlc3NCbG9jayh3b3Jkcywgb2Zmc2V0KTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgX2RvRmluYWxpemU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRcblx0ICAgICAgICAgICAgdmFyIHBhZGRpbmcgPSB0aGlzLmNmZy5wYWRkaW5nO1xuXG5cdCAgICAgICAgICAgIC8vIEZpbmFsaXplXG5cdCAgICAgICAgICAgIGlmICh0aGlzLl94Zm9ybU1vZGUgPT0gdGhpcy5fRU5DX1hGT1JNX01PREUpIHtcblx0ICAgICAgICAgICAgICAgIC8vIFBhZCBkYXRhXG5cdCAgICAgICAgICAgICAgICBwYWRkaW5nLnBhZCh0aGlzLl9kYXRhLCB0aGlzLmJsb2NrU2l6ZSk7XG5cblx0ICAgICAgICAgICAgICAgIC8vIFByb2Nlc3MgZmluYWwgYmxvY2tzXG5cdCAgICAgICAgICAgICAgICB2YXIgZmluYWxQcm9jZXNzZWRCbG9ja3MgPSB0aGlzLl9wcm9jZXNzKCEhJ2ZsdXNoJyk7XG5cdCAgICAgICAgICAgIH0gZWxzZSAvKiBpZiAodGhpcy5feGZvcm1Nb2RlID09IHRoaXMuX0RFQ19YRk9STV9NT0RFKSAqLyB7XG5cdCAgICAgICAgICAgICAgICAvLyBQcm9jZXNzIGZpbmFsIGJsb2Nrc1xuXHQgICAgICAgICAgICAgICAgdmFyIGZpbmFsUHJvY2Vzc2VkQmxvY2tzID0gdGhpcy5fcHJvY2VzcyghISdmbHVzaCcpO1xuXG5cdCAgICAgICAgICAgICAgICAvLyBVbnBhZCBkYXRhXG5cdCAgICAgICAgICAgICAgICBwYWRkaW5nLnVucGFkKGZpbmFsUHJvY2Vzc2VkQmxvY2tzKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIHJldHVybiBmaW5hbFByb2Nlc3NlZEJsb2Nrcztcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgYmxvY2tTaXplOiAxMjgvMzJcblx0ICAgIH0pO1xuXG5cdCAgICAvKipcblx0ICAgICAqIEEgY29sbGVjdGlvbiBvZiBjaXBoZXIgcGFyYW1ldGVycy5cblx0ICAgICAqXG5cdCAgICAgKiBAcHJvcGVydHkge1dvcmRBcnJheX0gY2lwaGVydGV4dCBUaGUgcmF3IGNpcGhlcnRleHQuXG5cdCAgICAgKiBAcHJvcGVydHkge1dvcmRBcnJheX0ga2V5IFRoZSBrZXkgdG8gdGhpcyBjaXBoZXJ0ZXh0LlxuXHQgICAgICogQHByb3BlcnR5IHtXb3JkQXJyYXl9IGl2IFRoZSBJViB1c2VkIGluIHRoZSBjaXBoZXJpbmcgb3BlcmF0aW9uLlxuXHQgICAgICogQHByb3BlcnR5IHtXb3JkQXJyYXl9IHNhbHQgVGhlIHNhbHQgdXNlZCB3aXRoIGEga2V5IGRlcml2YXRpb24gZnVuY3Rpb24uXG5cdCAgICAgKiBAcHJvcGVydHkge0NpcGhlcn0gYWxnb3JpdGhtIFRoZSBjaXBoZXIgYWxnb3JpdGhtLlxuXHQgICAgICogQHByb3BlcnR5IHtNb2RlfSBtb2RlIFRoZSBibG9jayBtb2RlIHVzZWQgaW4gdGhlIGNpcGhlcmluZyBvcGVyYXRpb24uXG5cdCAgICAgKiBAcHJvcGVydHkge1BhZGRpbmd9IHBhZGRpbmcgVGhlIHBhZGRpbmcgc2NoZW1lIHVzZWQgaW4gdGhlIGNpcGhlcmluZyBvcGVyYXRpb24uXG5cdCAgICAgKiBAcHJvcGVydHkge251bWJlcn0gYmxvY2tTaXplIFRoZSBibG9jayBzaXplIG9mIHRoZSBjaXBoZXIuXG5cdCAgICAgKiBAcHJvcGVydHkge0Zvcm1hdH0gZm9ybWF0dGVyIFRoZSBkZWZhdWx0IGZvcm1hdHRpbmcgc3RyYXRlZ3kgdG8gY29udmVydCB0aGlzIGNpcGhlciBwYXJhbXMgb2JqZWN0IHRvIGEgc3RyaW5nLlxuXHQgICAgICovXG5cdCAgICB2YXIgQ2lwaGVyUGFyYW1zID0gQ19saWIuQ2lwaGVyUGFyYW1zID0gQmFzZS5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEluaXRpYWxpemVzIGEgbmV3bHkgY3JlYXRlZCBjaXBoZXIgcGFyYW1zIG9iamVjdC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjaXBoZXJQYXJhbXMgQW4gb2JqZWN0IHdpdGggYW55IG9mIHRoZSBwb3NzaWJsZSBjaXBoZXIgcGFyYW1ldGVycy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGNpcGhlclBhcmFtcyA9IENyeXB0b0pTLmxpYi5DaXBoZXJQYXJhbXMuY3JlYXRlKHtcblx0ICAgICAgICAgKiAgICAgICAgIGNpcGhlcnRleHQ6IGNpcGhlcnRleHRXb3JkQXJyYXksXG5cdCAgICAgICAgICogICAgICAgICBrZXk6IGtleVdvcmRBcnJheSxcblx0ICAgICAgICAgKiAgICAgICAgIGl2OiBpdldvcmRBcnJheSxcblx0ICAgICAgICAgKiAgICAgICAgIHNhbHQ6IHNhbHRXb3JkQXJyYXksXG5cdCAgICAgICAgICogICAgICAgICBhbGdvcml0aG06IENyeXB0b0pTLmFsZ28uQUVTLFxuXHQgICAgICAgICAqICAgICAgICAgbW9kZTogQ3J5cHRvSlMubW9kZS5DQkMsXG5cdCAgICAgICAgICogICAgICAgICBwYWRkaW5nOiBDcnlwdG9KUy5wYWQuUEtDUzcsXG5cdCAgICAgICAgICogICAgICAgICBibG9ja1NpemU6IDQsXG5cdCAgICAgICAgICogICAgICAgICBmb3JtYXR0ZXI6IENyeXB0b0pTLmZvcm1hdC5PcGVuU1NMXG5cdCAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGluaXQ6IGZ1bmN0aW9uIChjaXBoZXJQYXJhbXMpIHtcblx0ICAgICAgICAgICAgdGhpcy5taXhJbihjaXBoZXJQYXJhbXMpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyB0aGlzIGNpcGhlciBwYXJhbXMgb2JqZWN0IHRvIGEgc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtGb3JtYXR9IGZvcm1hdHRlciAoT3B0aW9uYWwpIFRoZSBmb3JtYXR0aW5nIHN0cmF0ZWd5IHRvIHVzZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHN0cmluZ2lmaWVkIGNpcGhlciBwYXJhbXMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAdGhyb3dzIEVycm9yIElmIG5laXRoZXIgdGhlIGZvcm1hdHRlciBub3IgdGhlIGRlZmF1bHQgZm9ybWF0dGVyIGlzIHNldC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIHN0cmluZyA9IGNpcGhlclBhcmFtcyArICcnO1xuXHQgICAgICAgICAqICAgICB2YXIgc3RyaW5nID0gY2lwaGVyUGFyYW1zLnRvU3RyaW5nKCk7XG5cdCAgICAgICAgICogICAgIHZhciBzdHJpbmcgPSBjaXBoZXJQYXJhbXMudG9TdHJpbmcoQ3J5cHRvSlMuZm9ybWF0Lk9wZW5TU0wpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHRvU3RyaW5nOiBmdW5jdGlvbiAoZm9ybWF0dGVyKSB7XG5cdCAgICAgICAgICAgIHJldHVybiAoZm9ybWF0dGVyIHx8IHRoaXMuZm9ybWF0dGVyKS5zdHJpbmdpZnkodGhpcyk7XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogRm9ybWF0IG5hbWVzcGFjZS5cblx0ICAgICAqL1xuXHQgICAgdmFyIENfZm9ybWF0ID0gQy5mb3JtYXQgPSB7fTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBPcGVuU1NMIGZvcm1hdHRpbmcgc3RyYXRlZ3kuXG5cdCAgICAgKi9cblx0ICAgIHZhciBPcGVuU1NMRm9ybWF0dGVyID0gQ19mb3JtYXQuT3BlblNTTCA9IHtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIGNpcGhlciBwYXJhbXMgb2JqZWN0IHRvIGFuIE9wZW5TU0wtY29tcGF0aWJsZSBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0NpcGhlclBhcmFtc30gY2lwaGVyUGFyYW1zIFRoZSBjaXBoZXIgcGFyYW1zIG9iamVjdC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIE9wZW5TU0wtY29tcGF0aWJsZSBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBvcGVuU1NMU3RyaW5nID0gQ3J5cHRvSlMuZm9ybWF0Lk9wZW5TU0wuc3RyaW5naWZ5KGNpcGhlclBhcmFtcyk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgc3RyaW5naWZ5OiBmdW5jdGlvbiAoY2lwaGVyUGFyYW1zKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgY2lwaGVydGV4dCA9IGNpcGhlclBhcmFtcy5jaXBoZXJ0ZXh0O1xuXHQgICAgICAgICAgICB2YXIgc2FsdCA9IGNpcGhlclBhcmFtcy5zYWx0O1xuXG5cdCAgICAgICAgICAgIC8vIEZvcm1hdFxuXHQgICAgICAgICAgICBpZiAoc2FsdCkge1xuXHQgICAgICAgICAgICAgICAgdmFyIHdvcmRBcnJheSA9IFdvcmRBcnJheS5jcmVhdGUoWzB4NTM2MTZjNzQsIDB4NjU2NDVmNWZdKS5jb25jYXQoc2FsdCkuY29uY2F0KGNpcGhlcnRleHQpO1xuXHQgICAgICAgICAgICB9IGVsc2Uge1xuXHQgICAgICAgICAgICAgICAgdmFyIHdvcmRBcnJheSA9IGNpcGhlcnRleHQ7XG5cdCAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICByZXR1cm4gd29yZEFycmF5LnRvU3RyaW5nKEJhc2U2NCk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbnZlcnRzIGFuIE9wZW5TU0wtY29tcGF0aWJsZSBzdHJpbmcgdG8gYSBjaXBoZXIgcGFyYW1zIG9iamVjdC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBvcGVuU1NMU3RyIFRoZSBPcGVuU1NMLWNvbXBhdGlibGUgc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7Q2lwaGVyUGFyYW1zfSBUaGUgY2lwaGVyIHBhcmFtcyBvYmplY3QuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBjaXBoZXJQYXJhbXMgPSBDcnlwdG9KUy5mb3JtYXQuT3BlblNTTC5wYXJzZShvcGVuU1NMU3RyaW5nKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBwYXJzZTogZnVuY3Rpb24gKG9wZW5TU0xTdHIpIHtcblx0ICAgICAgICAgICAgLy8gUGFyc2UgYmFzZTY0XG5cdCAgICAgICAgICAgIHZhciBjaXBoZXJ0ZXh0ID0gQmFzZTY0LnBhcnNlKG9wZW5TU0xTdHIpO1xuXG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0XG5cdCAgICAgICAgICAgIHZhciBjaXBoZXJ0ZXh0V29yZHMgPSBjaXBoZXJ0ZXh0LndvcmRzO1xuXG5cdCAgICAgICAgICAgIC8vIFRlc3QgZm9yIHNhbHRcblx0ICAgICAgICAgICAgaWYgKGNpcGhlcnRleHRXb3Jkc1swXSA9PSAweDUzNjE2Yzc0ICYmIGNpcGhlcnRleHRXb3Jkc1sxXSA9PSAweDY1NjQ1ZjVmKSB7XG5cdCAgICAgICAgICAgICAgICAvLyBFeHRyYWN0IHNhbHRcblx0ICAgICAgICAgICAgICAgIHZhciBzYWx0ID0gV29yZEFycmF5LmNyZWF0ZShjaXBoZXJ0ZXh0V29yZHMuc2xpY2UoMiwgNCkpO1xuXG5cdCAgICAgICAgICAgICAgICAvLyBSZW1vdmUgc2FsdCBmcm9tIGNpcGhlcnRleHRcblx0ICAgICAgICAgICAgICAgIGNpcGhlcnRleHRXb3Jkcy5zcGxpY2UoMCwgNCk7XG5cdCAgICAgICAgICAgICAgICBjaXBoZXJ0ZXh0LnNpZ0J5dGVzIC09IDE2O1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIENpcGhlclBhcmFtcy5jcmVhdGUoeyBjaXBoZXJ0ZXh0OiBjaXBoZXJ0ZXh0LCBzYWx0OiBzYWx0IH0pO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cblx0ICAgIC8qKlxuXHQgICAgICogQSBjaXBoZXIgd3JhcHBlciB0aGF0IHJldHVybnMgY2lwaGVydGV4dCBhcyBhIHNlcmlhbGl6YWJsZSBjaXBoZXIgcGFyYW1zIG9iamVjdC5cblx0ICAgICAqL1xuXHQgICAgdmFyIFNlcmlhbGl6YWJsZUNpcGhlciA9IENfbGliLlNlcmlhbGl6YWJsZUNpcGhlciA9IEJhc2UuZXh0ZW5kKHtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb25maWd1cmF0aW9uIG9wdGlvbnMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcHJvcGVydHkge0Zvcm1hdHRlcn0gZm9ybWF0IFRoZSBmb3JtYXR0aW5nIHN0cmF0ZWd5IHRvIGNvbnZlcnQgY2lwaGVyIHBhcmFtIG9iamVjdHMgdG8gYW5kIGZyb20gYSBzdHJpbmcuIERlZmF1bHQ6IE9wZW5TU0xcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBjZmc6IEJhc2UuZXh0ZW5kKHtcblx0ICAgICAgICAgICAgZm9ybWF0OiBPcGVuU1NMRm9ybWF0dGVyXG5cdCAgICAgICAgfSksXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBFbmNyeXB0cyBhIG1lc3NhZ2UuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0NpcGhlcn0gY2lwaGVyIFRoZSBjaXBoZXIgYWxnb3JpdGhtIHRvIHVzZS5cblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gZW5jcnlwdC5cblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheX0ga2V5IFRoZSBrZXkuXG5cdCAgICAgICAgICogQHBhcmFtIHtPYmplY3R9IGNmZyAoT3B0aW9uYWwpIFRoZSBjb25maWd1cmF0aW9uIG9wdGlvbnMgdG8gdXNlIGZvciB0aGlzIG9wZXJhdGlvbi5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge0NpcGhlclBhcmFtc30gQSBjaXBoZXIgcGFyYW1zIG9iamVjdC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGNpcGhlcnRleHRQYXJhbXMgPSBDcnlwdG9KUy5saWIuU2VyaWFsaXphYmxlQ2lwaGVyLmVuY3J5cHQoQ3J5cHRvSlMuYWxnby5BRVMsIG1lc3NhZ2UsIGtleSk7XG5cdCAgICAgICAgICogICAgIHZhciBjaXBoZXJ0ZXh0UGFyYW1zID0gQ3J5cHRvSlMubGliLlNlcmlhbGl6YWJsZUNpcGhlci5lbmNyeXB0KENyeXB0b0pTLmFsZ28uQUVTLCBtZXNzYWdlLCBrZXksIHsgaXY6IGl2IH0pO1xuXHQgICAgICAgICAqICAgICB2YXIgY2lwaGVydGV4dFBhcmFtcyA9IENyeXB0b0pTLmxpYi5TZXJpYWxpemFibGVDaXBoZXIuZW5jcnlwdChDcnlwdG9KUy5hbGdvLkFFUywgbWVzc2FnZSwga2V5LCB7IGl2OiBpdiwgZm9ybWF0OiBDcnlwdG9KUy5mb3JtYXQuT3BlblNTTCB9KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBlbmNyeXB0OiBmdW5jdGlvbiAoY2lwaGVyLCBtZXNzYWdlLCBrZXksIGNmZykge1xuXHQgICAgICAgICAgICAvLyBBcHBseSBjb25maWcgZGVmYXVsdHNcblx0ICAgICAgICAgICAgY2ZnID0gdGhpcy5jZmcuZXh0ZW5kKGNmZyk7XG5cblx0ICAgICAgICAgICAgLy8gRW5jcnlwdFxuXHQgICAgICAgICAgICB2YXIgZW5jcnlwdG9yID0gY2lwaGVyLmNyZWF0ZUVuY3J5cHRvcihrZXksIGNmZyk7XG5cdCAgICAgICAgICAgIHZhciBjaXBoZXJ0ZXh0ID0gZW5jcnlwdG9yLmZpbmFsaXplKG1lc3NhZ2UpO1xuXG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0XG5cdCAgICAgICAgICAgIHZhciBjaXBoZXJDZmcgPSBlbmNyeXB0b3IuY2ZnO1xuXG5cdCAgICAgICAgICAgIC8vIENyZWF0ZSBhbmQgcmV0dXJuIHNlcmlhbGl6YWJsZSBjaXBoZXIgcGFyYW1zXG5cdCAgICAgICAgICAgIHJldHVybiBDaXBoZXJQYXJhbXMuY3JlYXRlKHtcblx0ICAgICAgICAgICAgICAgIGNpcGhlcnRleHQ6IGNpcGhlcnRleHQsXG5cdCAgICAgICAgICAgICAgICBrZXk6IGtleSxcblx0ICAgICAgICAgICAgICAgIGl2OiBjaXBoZXJDZmcuaXYsXG5cdCAgICAgICAgICAgICAgICBhbGdvcml0aG06IGNpcGhlcixcblx0ICAgICAgICAgICAgICAgIG1vZGU6IGNpcGhlckNmZy5tb2RlLFxuXHQgICAgICAgICAgICAgICAgcGFkZGluZzogY2lwaGVyQ2ZnLnBhZGRpbmcsXG5cdCAgICAgICAgICAgICAgICBibG9ja1NpemU6IGNpcGhlci5ibG9ja1NpemUsXG5cdCAgICAgICAgICAgICAgICBmb3JtYXR0ZXI6IGNmZy5mb3JtYXRcblx0ICAgICAgICAgICAgfSk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIERlY3J5cHRzIHNlcmlhbGl6ZWQgY2lwaGVydGV4dC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7Q2lwaGVyfSBjaXBoZXIgVGhlIGNpcGhlciBhbGdvcml0aG0gdG8gdXNlLlxuXHQgICAgICAgICAqIEBwYXJhbSB7Q2lwaGVyUGFyYW1zfHN0cmluZ30gY2lwaGVydGV4dCBUaGUgY2lwaGVydGV4dCB0byBkZWNyeXB0LlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fSBrZXkgVGhlIGtleS5cblx0ICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gY2ZnIChPcHRpb25hbCkgVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byB1c2UgZm9yIHRoaXMgb3BlcmF0aW9uLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgcGxhaW50ZXh0LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgcGxhaW50ZXh0ID0gQ3J5cHRvSlMubGliLlNlcmlhbGl6YWJsZUNpcGhlci5kZWNyeXB0KENyeXB0b0pTLmFsZ28uQUVTLCBmb3JtYXR0ZWRDaXBoZXJ0ZXh0LCBrZXksIHsgaXY6IGl2LCBmb3JtYXQ6IENyeXB0b0pTLmZvcm1hdC5PcGVuU1NMIH0pO1xuXHQgICAgICAgICAqICAgICB2YXIgcGxhaW50ZXh0ID0gQ3J5cHRvSlMubGliLlNlcmlhbGl6YWJsZUNpcGhlci5kZWNyeXB0KENyeXB0b0pTLmFsZ28uQUVTLCBjaXBoZXJ0ZXh0UGFyYW1zLCBrZXksIHsgaXY6IGl2LCBmb3JtYXQ6IENyeXB0b0pTLmZvcm1hdC5PcGVuU1NMIH0pO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGRlY3J5cHQ6IGZ1bmN0aW9uIChjaXBoZXIsIGNpcGhlcnRleHQsIGtleSwgY2ZnKSB7XG5cdCAgICAgICAgICAgIC8vIEFwcGx5IGNvbmZpZyBkZWZhdWx0c1xuXHQgICAgICAgICAgICBjZmcgPSB0aGlzLmNmZy5leHRlbmQoY2ZnKTtcblxuXHQgICAgICAgICAgICAvLyBDb252ZXJ0IHN0cmluZyB0byBDaXBoZXJQYXJhbXNcblx0ICAgICAgICAgICAgY2lwaGVydGV4dCA9IHRoaXMuX3BhcnNlKGNpcGhlcnRleHQsIGNmZy5mb3JtYXQpO1xuXG5cdCAgICAgICAgICAgIC8vIERlY3J5cHRcblx0ICAgICAgICAgICAgdmFyIHBsYWludGV4dCA9IGNpcGhlci5jcmVhdGVEZWNyeXB0b3Ioa2V5LCBjZmcpLmZpbmFsaXplKGNpcGhlcnRleHQuY2lwaGVydGV4dCk7XG5cblx0ICAgICAgICAgICAgcmV0dXJuIHBsYWludGV4dDtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgc2VyaWFsaXplZCBjaXBoZXJ0ZXh0IHRvIENpcGhlclBhcmFtcyxcblx0ICAgICAgICAgKiBlbHNlIGFzc3VtZWQgQ2lwaGVyUGFyYW1zIGFscmVhZHkgYW5kIHJldHVybnMgY2lwaGVydGV4dCB1bmNoYW5nZWQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0NpcGhlclBhcmFtc3xzdHJpbmd9IGNpcGhlcnRleHQgVGhlIGNpcGhlcnRleHQuXG5cdCAgICAgICAgICogQHBhcmFtIHtGb3JtYXR0ZXJ9IGZvcm1hdCBUaGUgZm9ybWF0dGluZyBzdHJhdGVneSB0byB1c2UgdG8gcGFyc2Ugc2VyaWFsaXplZCBjaXBoZXJ0ZXh0LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7Q2lwaGVyUGFyYW1zfSBUaGUgdW5zZXJpYWxpemVkIGNpcGhlcnRleHQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBjaXBoZXJ0ZXh0UGFyYW1zID0gQ3J5cHRvSlMubGliLlNlcmlhbGl6YWJsZUNpcGhlci5fcGFyc2UoY2lwaGVydGV4dFN0cmluZ09yUGFyYW1zLCBmb3JtYXQpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIF9wYXJzZTogZnVuY3Rpb24gKGNpcGhlcnRleHQsIGZvcm1hdCkge1xuXHQgICAgICAgICAgICBpZiAodHlwZW9mIGNpcGhlcnRleHQgPT0gJ3N0cmluZycpIHtcblx0ICAgICAgICAgICAgICAgIHJldHVybiBmb3JtYXQucGFyc2UoY2lwaGVydGV4dCwgdGhpcyk7XG5cdCAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICByZXR1cm4gY2lwaGVydGV4dDtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH1cblx0ICAgIH0pO1xuXG5cdCAgICAvKipcblx0ICAgICAqIEtleSBkZXJpdmF0aW9uIGZ1bmN0aW9uIG5hbWVzcGFjZS5cblx0ICAgICAqL1xuXHQgICAgdmFyIENfa2RmID0gQy5rZGYgPSB7fTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBPcGVuU1NMIGtleSBkZXJpdmF0aW9uIGZ1bmN0aW9uLlxuXHQgICAgICovXG5cdCAgICB2YXIgT3BlblNTTEtkZiA9IENfa2RmLk9wZW5TU0wgPSB7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogRGVyaXZlcyBhIGtleSBhbmQgSVYgZnJvbSBhIHBhc3N3b3JkLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHBhc3N3b3JkIFRoZSBwYXNzd29yZCB0byBkZXJpdmUgZnJvbS5cblx0ICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0ga2V5U2l6ZSBUaGUgc2l6ZSBpbiB3b3JkcyBvZiB0aGUga2V5IHRvIGdlbmVyYXRlLlxuXHQgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfSBpdlNpemUgVGhlIHNpemUgaW4gd29yZHMgb2YgdGhlIElWIHRvIGdlbmVyYXRlLlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30gc2FsdCAoT3B0aW9uYWwpIEEgNjQtYml0IHNhbHQgdG8gdXNlLiBJZiBvbWl0dGVkLCBhIHNhbHQgd2lsbCBiZSBnZW5lcmF0ZWQgcmFuZG9tbHkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtDaXBoZXJQYXJhbXN9IEEgY2lwaGVyIHBhcmFtcyBvYmplY3Qgd2l0aCB0aGUga2V5LCBJViwgYW5kIHNhbHQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBkZXJpdmVkUGFyYW1zID0gQ3J5cHRvSlMua2RmLk9wZW5TU0wuZXhlY3V0ZSgnUGFzc3dvcmQnLCAyNTYvMzIsIDEyOC8zMik7XG5cdCAgICAgICAgICogICAgIHZhciBkZXJpdmVkUGFyYW1zID0gQ3J5cHRvSlMua2RmLk9wZW5TU0wuZXhlY3V0ZSgnUGFzc3dvcmQnLCAyNTYvMzIsIDEyOC8zMiwgJ3NhbHRzYWx0Jyk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgZXhlY3V0ZTogZnVuY3Rpb24gKHBhc3N3b3JkLCBrZXlTaXplLCBpdlNpemUsIHNhbHQpIHtcblx0ICAgICAgICAgICAgLy8gR2VuZXJhdGUgcmFuZG9tIHNhbHRcblx0ICAgICAgICAgICAgaWYgKCFzYWx0KSB7XG5cdCAgICAgICAgICAgICAgICBzYWx0ID0gV29yZEFycmF5LnJhbmRvbSg2NC84KTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIERlcml2ZSBrZXkgYW5kIElWXG5cdCAgICAgICAgICAgIHZhciBrZXkgPSBFdnBLREYuY3JlYXRlKHsga2V5U2l6ZToga2V5U2l6ZSArIGl2U2l6ZSB9KS5jb21wdXRlKHBhc3N3b3JkLCBzYWx0KTtcblxuXHQgICAgICAgICAgICAvLyBTZXBhcmF0ZSBrZXkgYW5kIElWXG5cdCAgICAgICAgICAgIHZhciBpdiA9IFdvcmRBcnJheS5jcmVhdGUoa2V5LndvcmRzLnNsaWNlKGtleVNpemUpLCBpdlNpemUgKiA0KTtcblx0ICAgICAgICAgICAga2V5LnNpZ0J5dGVzID0ga2V5U2l6ZSAqIDQ7XG5cblx0ICAgICAgICAgICAgLy8gUmV0dXJuIHBhcmFtc1xuXHQgICAgICAgICAgICByZXR1cm4gQ2lwaGVyUGFyYW1zLmNyZWF0ZSh7IGtleToga2V5LCBpdjogaXYsIHNhbHQ6IHNhbHQgfSk7XG5cdCAgICAgICAgfVxuXHQgICAgfTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBBIHNlcmlhbGl6YWJsZSBjaXBoZXIgd3JhcHBlciB0aGF0IGRlcml2ZXMgdGhlIGtleSBmcm9tIGEgcGFzc3dvcmQsXG5cdCAgICAgKiBhbmQgcmV0dXJucyBjaXBoZXJ0ZXh0IGFzIGEgc2VyaWFsaXphYmxlIGNpcGhlciBwYXJhbXMgb2JqZWN0LlxuXHQgICAgICovXG5cdCAgICB2YXIgUGFzc3dvcmRCYXNlZENpcGhlciA9IENfbGliLlBhc3N3b3JkQmFzZWRDaXBoZXIgPSBTZXJpYWxpemFibGVDaXBoZXIuZXh0ZW5kKHtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb25maWd1cmF0aW9uIG9wdGlvbnMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcHJvcGVydHkge0tERn0ga2RmIFRoZSBrZXkgZGVyaXZhdGlvbiBmdW5jdGlvbiB0byB1c2UgdG8gZ2VuZXJhdGUgYSBrZXkgYW5kIElWIGZyb20gYSBwYXNzd29yZC4gRGVmYXVsdDogT3BlblNTTFxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNmZzogU2VyaWFsaXphYmxlQ2lwaGVyLmNmZy5leHRlbmQoe1xuXHQgICAgICAgICAgICBrZGY6IE9wZW5TU0xLZGZcblx0ICAgICAgICB9KSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIEVuY3J5cHRzIGEgbWVzc2FnZSB1c2luZyBhIHBhc3N3b3JkLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtDaXBoZXJ9IGNpcGhlciBUaGUgY2lwaGVyIGFsZ29yaXRobSB0byB1c2UuXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBtZXNzYWdlIFRoZSBtZXNzYWdlIHRvIGVuY3J5cHQuXG5cdCAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IHBhc3N3b3JkIFRoZSBwYXNzd29yZC5cblx0ICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gY2ZnIChPcHRpb25hbCkgVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byB1c2UgZm9yIHRoaXMgb3BlcmF0aW9uLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7Q2lwaGVyUGFyYW1zfSBBIGNpcGhlciBwYXJhbXMgb2JqZWN0LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgY2lwaGVydGV4dFBhcmFtcyA9IENyeXB0b0pTLmxpYi5QYXNzd29yZEJhc2VkQ2lwaGVyLmVuY3J5cHQoQ3J5cHRvSlMuYWxnby5BRVMsIG1lc3NhZ2UsICdwYXNzd29yZCcpO1xuXHQgICAgICAgICAqICAgICB2YXIgY2lwaGVydGV4dFBhcmFtcyA9IENyeXB0b0pTLmxpYi5QYXNzd29yZEJhc2VkQ2lwaGVyLmVuY3J5cHQoQ3J5cHRvSlMuYWxnby5BRVMsIG1lc3NhZ2UsICdwYXNzd29yZCcsIHsgZm9ybWF0OiBDcnlwdG9KUy5mb3JtYXQuT3BlblNTTCB9KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBlbmNyeXB0OiBmdW5jdGlvbiAoY2lwaGVyLCBtZXNzYWdlLCBwYXNzd29yZCwgY2ZnKSB7XG5cdCAgICAgICAgICAgIC8vIEFwcGx5IGNvbmZpZyBkZWZhdWx0c1xuXHQgICAgICAgICAgICBjZmcgPSB0aGlzLmNmZy5leHRlbmQoY2ZnKTtcblxuXHQgICAgICAgICAgICAvLyBEZXJpdmUga2V5IGFuZCBvdGhlciBwYXJhbXNcblx0ICAgICAgICAgICAgdmFyIGRlcml2ZWRQYXJhbXMgPSBjZmcua2RmLmV4ZWN1dGUocGFzc3dvcmQsIGNpcGhlci5rZXlTaXplLCBjaXBoZXIuaXZTaXplKTtcblxuXHQgICAgICAgICAgICAvLyBBZGQgSVYgdG8gY29uZmlnXG5cdCAgICAgICAgICAgIGNmZy5pdiA9IGRlcml2ZWRQYXJhbXMuaXY7XG5cblx0ICAgICAgICAgICAgLy8gRW5jcnlwdFxuXHQgICAgICAgICAgICB2YXIgY2lwaGVydGV4dCA9IFNlcmlhbGl6YWJsZUNpcGhlci5lbmNyeXB0LmNhbGwodGhpcywgY2lwaGVyLCBtZXNzYWdlLCBkZXJpdmVkUGFyYW1zLmtleSwgY2ZnKTtcblxuXHQgICAgICAgICAgICAvLyBNaXggaW4gZGVyaXZlZCBwYXJhbXNcblx0ICAgICAgICAgICAgY2lwaGVydGV4dC5taXhJbihkZXJpdmVkUGFyYW1zKTtcblxuXHQgICAgICAgICAgICByZXR1cm4gY2lwaGVydGV4dDtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogRGVjcnlwdHMgc2VyaWFsaXplZCBjaXBoZXJ0ZXh0IHVzaW5nIGEgcGFzc3dvcmQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0NpcGhlcn0gY2lwaGVyIFRoZSBjaXBoZXIgYWxnb3JpdGhtIHRvIHVzZS5cblx0ICAgICAgICAgKiBAcGFyYW0ge0NpcGhlclBhcmFtc3xzdHJpbmd9IGNpcGhlcnRleHQgVGhlIGNpcGhlcnRleHQgdG8gZGVjcnlwdC5cblx0ICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gcGFzc3dvcmQgVGhlIHBhc3N3b3JkLlxuXHQgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjZmcgKE9wdGlvbmFsKSBUaGUgY29uZmlndXJhdGlvbiBvcHRpb25zIHRvIHVzZSBmb3IgdGhpcyBvcGVyYXRpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBwbGFpbnRleHQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBwbGFpbnRleHQgPSBDcnlwdG9KUy5saWIuUGFzc3dvcmRCYXNlZENpcGhlci5kZWNyeXB0KENyeXB0b0pTLmFsZ28uQUVTLCBmb3JtYXR0ZWRDaXBoZXJ0ZXh0LCAncGFzc3dvcmQnLCB7IGZvcm1hdDogQ3J5cHRvSlMuZm9ybWF0Lk9wZW5TU0wgfSk7XG5cdCAgICAgICAgICogICAgIHZhciBwbGFpbnRleHQgPSBDcnlwdG9KUy5saWIuUGFzc3dvcmRCYXNlZENpcGhlci5kZWNyeXB0KENyeXB0b0pTLmFsZ28uQUVTLCBjaXBoZXJ0ZXh0UGFyYW1zLCAncGFzc3dvcmQnLCB7IGZvcm1hdDogQ3J5cHRvSlMuZm9ybWF0Lk9wZW5TU0wgfSk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgZGVjcnlwdDogZnVuY3Rpb24gKGNpcGhlciwgY2lwaGVydGV4dCwgcGFzc3dvcmQsIGNmZykge1xuXHQgICAgICAgICAgICAvLyBBcHBseSBjb25maWcgZGVmYXVsdHNcblx0ICAgICAgICAgICAgY2ZnID0gdGhpcy5jZmcuZXh0ZW5kKGNmZyk7XG5cblx0ICAgICAgICAgICAgLy8gQ29udmVydCBzdHJpbmcgdG8gQ2lwaGVyUGFyYW1zXG5cdCAgICAgICAgICAgIGNpcGhlcnRleHQgPSB0aGlzLl9wYXJzZShjaXBoZXJ0ZXh0LCBjZmcuZm9ybWF0KTtcblxuXHQgICAgICAgICAgICAvLyBEZXJpdmUga2V5IGFuZCBvdGhlciBwYXJhbXNcblx0ICAgICAgICAgICAgdmFyIGRlcml2ZWRQYXJhbXMgPSBjZmcua2RmLmV4ZWN1dGUocGFzc3dvcmQsIGNpcGhlci5rZXlTaXplLCBjaXBoZXIuaXZTaXplLCBjaXBoZXJ0ZXh0LnNhbHQpO1xuXG5cdCAgICAgICAgICAgIC8vIEFkZCBJViB0byBjb25maWdcblx0ICAgICAgICAgICAgY2ZnLml2ID0gZGVyaXZlZFBhcmFtcy5pdjtcblxuXHQgICAgICAgICAgICAvLyBEZWNyeXB0XG5cdCAgICAgICAgICAgIHZhciBwbGFpbnRleHQgPSBTZXJpYWxpemFibGVDaXBoZXIuZGVjcnlwdC5jYWxsKHRoaXMsIGNpcGhlciwgY2lwaGVydGV4dCwgZGVyaXZlZFBhcmFtcy5rZXksIGNmZyk7XG5cblx0ICAgICAgICAgICAgcmV0dXJuIHBsYWludGV4dDtcblx0ICAgICAgICB9XG5cdCAgICB9KTtcblx0fSgpKTtcblxuXG59KSk7IiwiOyhmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuXHRpZiAodHlwZW9mIGV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcblx0XHQvLyBDb21tb25KU1xuXHRcdG1vZHVsZS5leHBvcnRzID0gZXhwb3J0cyA9IGZhY3RvcnkoKTtcblx0fVxuXHRlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuXHRcdC8vIEFNRFxuXHRcdGRlZmluZShbXSwgZmFjdG9yeSk7XG5cdH1cblx0ZWxzZSB7XG5cdFx0Ly8gR2xvYmFsIChicm93c2VyKVxuXHRcdHJvb3QuQ3J5cHRvSlMgPSBmYWN0b3J5KCk7XG5cdH1cbn0odGhpcywgZnVuY3Rpb24gKCkge1xuXG5cdC8qKlxuXHQgKiBDcnlwdG9KUyBjb3JlIGNvbXBvbmVudHMuXG5cdCAqL1xuXHR2YXIgQ3J5cHRvSlMgPSBDcnlwdG9KUyB8fCAoZnVuY3Rpb24gKE1hdGgsIHVuZGVmaW5lZCkge1xuXHQgICAgLypcblx0ICAgICAqIExvY2FsIHBvbHlmaWwgb2YgT2JqZWN0LmNyZWF0ZVxuXHQgICAgICovXG5cdCAgICB2YXIgY3JlYXRlID0gT2JqZWN0LmNyZWF0ZSB8fCAoZnVuY3Rpb24gKCkge1xuXHQgICAgICAgIGZ1bmN0aW9uIEYoKSB7fTtcblxuXHQgICAgICAgIHJldHVybiBmdW5jdGlvbiAob2JqKSB7XG5cdCAgICAgICAgICAgIHZhciBzdWJ0eXBlO1xuXG5cdCAgICAgICAgICAgIEYucHJvdG90eXBlID0gb2JqO1xuXG5cdCAgICAgICAgICAgIHN1YnR5cGUgPSBuZXcgRigpO1xuXG5cdCAgICAgICAgICAgIEYucHJvdG90eXBlID0gbnVsbDtcblxuXHQgICAgICAgICAgICByZXR1cm4gc3VidHlwZTtcblx0ICAgICAgICB9O1xuXHQgICAgfSgpKVxuXG5cdCAgICAvKipcblx0ICAgICAqIENyeXB0b0pTIG5hbWVzcGFjZS5cblx0ICAgICAqL1xuXHQgICAgdmFyIEMgPSB7fTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBMaWJyYXJ5IG5hbWVzcGFjZS5cblx0ICAgICAqL1xuXHQgICAgdmFyIENfbGliID0gQy5saWIgPSB7fTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBCYXNlIG9iamVjdCBmb3IgcHJvdG90eXBhbCBpbmhlcml0YW5jZS5cblx0ICAgICAqL1xuXHQgICAgdmFyIEJhc2UgPSBDX2xpYi5CYXNlID0gKGZ1bmN0aW9uICgpIHtcblxuXG5cdCAgICAgICAgcmV0dXJuIHtcblx0ICAgICAgICAgICAgLyoqXG5cdCAgICAgICAgICAgICAqIENyZWF0ZXMgYSBuZXcgb2JqZWN0IHRoYXQgaW5oZXJpdHMgZnJvbSB0aGlzIG9iamVjdC5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQHBhcmFtIHtPYmplY3R9IG92ZXJyaWRlcyBQcm9wZXJ0aWVzIHRvIGNvcHkgaW50byB0aGUgbmV3IG9iamVjdC5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQHJldHVybiB7T2JqZWN0fSBUaGUgbmV3IG9iamVjdC5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiAgICAgdmFyIE15VHlwZSA9IENyeXB0b0pTLmxpYi5CYXNlLmV4dGVuZCh7XG5cdCAgICAgICAgICAgICAqICAgICAgICAgZmllbGQ6ICd2YWx1ZScsXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqICAgICAgICAgbWV0aG9kOiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgICAqICAgICAgICAgfVxuXHQgICAgICAgICAgICAgKiAgICAgfSk7XG5cdCAgICAgICAgICAgICAqL1xuXHQgICAgICAgICAgICBleHRlbmQ6IGZ1bmN0aW9uIChvdmVycmlkZXMpIHtcblx0ICAgICAgICAgICAgICAgIC8vIFNwYXduXG5cdCAgICAgICAgICAgICAgICB2YXIgc3VidHlwZSA9IGNyZWF0ZSh0aGlzKTtcblxuXHQgICAgICAgICAgICAgICAgLy8gQXVnbWVudFxuXHQgICAgICAgICAgICAgICAgaWYgKG92ZXJyaWRlcykge1xuXHQgICAgICAgICAgICAgICAgICAgIHN1YnR5cGUubWl4SW4ob3ZlcnJpZGVzKTtcblx0ICAgICAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICAgICAgLy8gQ3JlYXRlIGRlZmF1bHQgaW5pdGlhbGl6ZXJcblx0ICAgICAgICAgICAgICAgIGlmICghc3VidHlwZS5oYXNPd25Qcm9wZXJ0eSgnaW5pdCcpIHx8IHRoaXMuaW5pdCA9PT0gc3VidHlwZS5pbml0KSB7XG5cdCAgICAgICAgICAgICAgICAgICAgc3VidHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAgICAgICAgICAgICBzdWJ0eXBlLiRzdXBlci5pbml0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG5cdCAgICAgICAgICAgICAgICAgICAgfTtcblx0ICAgICAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZXIncyBwcm90b3R5cGUgaXMgdGhlIHN1YnR5cGUgb2JqZWN0XG5cdCAgICAgICAgICAgICAgICBzdWJ0eXBlLmluaXQucHJvdG90eXBlID0gc3VidHlwZTtcblxuXHQgICAgICAgICAgICAgICAgLy8gUmVmZXJlbmNlIHN1cGVydHlwZVxuXHQgICAgICAgICAgICAgICAgc3VidHlwZS4kc3VwZXIgPSB0aGlzO1xuXG5cdCAgICAgICAgICAgICAgICByZXR1cm4gc3VidHlwZTtcblx0ICAgICAgICAgICAgfSxcblxuXHQgICAgICAgICAgICAvKipcblx0ICAgICAgICAgICAgICogRXh0ZW5kcyB0aGlzIG9iamVjdCBhbmQgcnVucyB0aGUgaW5pdCBtZXRob2QuXG5cdCAgICAgICAgICAgICAqIEFyZ3VtZW50cyB0byBjcmVhdGUoKSB3aWxsIGJlIHBhc3NlZCB0byBpbml0KCkuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEByZXR1cm4ge09iamVjdH0gVGhlIG5ldyBvYmplY3QuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogICAgIHZhciBpbnN0YW5jZSA9IE15VHlwZS5jcmVhdGUoKTtcblx0ICAgICAgICAgICAgICovXG5cdCAgICAgICAgICAgIGNyZWF0ZTogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAgICAgdmFyIGluc3RhbmNlID0gdGhpcy5leHRlbmQoKTtcblx0ICAgICAgICAgICAgICAgIGluc3RhbmNlLmluaXQuYXBwbHkoaW5zdGFuY2UsIGFyZ3VtZW50cyk7XG5cblx0ICAgICAgICAgICAgICAgIHJldHVybiBpbnN0YW5jZTtcblx0ICAgICAgICAgICAgfSxcblxuXHQgICAgICAgICAgICAvKipcblx0ICAgICAgICAgICAgICogSW5pdGlhbGl6ZXMgYSBuZXdseSBjcmVhdGVkIG9iamVjdC5cblx0ICAgICAgICAgICAgICogT3ZlcnJpZGUgdGhpcyBtZXRob2QgdG8gYWRkIHNvbWUgbG9naWMgd2hlbiB5b3VyIG9iamVjdHMgYXJlIGNyZWF0ZWQuXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqICAgICB2YXIgTXlUeXBlID0gQ3J5cHRvSlMubGliLkJhc2UuZXh0ZW5kKHtcblx0ICAgICAgICAgICAgICogICAgICAgICBpbml0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgICAqICAgICAgICAgICAgIC8vIC4uLlxuXHQgICAgICAgICAgICAgKiAgICAgICAgIH1cblx0ICAgICAgICAgICAgICogICAgIH0pO1xuXHQgICAgICAgICAgICAgKi9cblx0ICAgICAgICAgICAgaW5pdDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICB9LFxuXG5cdCAgICAgICAgICAgIC8qKlxuXHQgICAgICAgICAgICAgKiBDb3BpZXMgcHJvcGVydGllcyBpbnRvIHRoaXMgb2JqZWN0LlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gcHJvcGVydGllcyBUaGUgcHJvcGVydGllcyB0byBtaXggaW4uXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICAgICAqXG5cdCAgICAgICAgICAgICAqICAgICBNeVR5cGUubWl4SW4oe1xuXHQgICAgICAgICAgICAgKiAgICAgICAgIGZpZWxkOiAndmFsdWUnXG5cdCAgICAgICAgICAgICAqICAgICB9KTtcblx0ICAgICAgICAgICAgICovXG5cdCAgICAgICAgICAgIG1peEluOiBmdW5jdGlvbiAocHJvcGVydGllcykge1xuXHQgICAgICAgICAgICAgICAgZm9yICh2YXIgcHJvcGVydHlOYW1lIGluIHByb3BlcnRpZXMpIHtcblx0ICAgICAgICAgICAgICAgICAgICBpZiAocHJvcGVydGllcy5oYXNPd25Qcm9wZXJ0eShwcm9wZXJ0eU5hbWUpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgICAgIHRoaXNbcHJvcGVydHlOYW1lXSA9IHByb3BlcnRpZXNbcHJvcGVydHlOYW1lXTtcblx0ICAgICAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIC8vIElFIHdvbid0IGNvcHkgdG9TdHJpbmcgdXNpbmcgdGhlIGxvb3AgYWJvdmVcblx0ICAgICAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmhhc093blByb3BlcnR5KCd0b1N0cmluZycpKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdGhpcy50b1N0cmluZyA9IHByb3BlcnRpZXMudG9TdHJpbmc7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH0sXG5cblx0ICAgICAgICAgICAgLyoqXG5cdCAgICAgICAgICAgICAqIENyZWF0ZXMgYSBjb3B5IG9mIHRoaXMgb2JqZWN0LlxuXHQgICAgICAgICAgICAgKlxuXHQgICAgICAgICAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBjbG9uZS5cblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgICAgICpcblx0ICAgICAgICAgICAgICogICAgIHZhciBjbG9uZSA9IGluc3RhbmNlLmNsb25lKCk7XG5cdCAgICAgICAgICAgICAqL1xuXHQgICAgICAgICAgICBjbG9uZTogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuaW5pdC5wcm90b3R5cGUuZXh0ZW5kKHRoaXMpO1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfTtcblx0ICAgIH0oKSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogQW4gYXJyYXkgb2YgMzItYml0IHdvcmRzLlxuXHQgICAgICpcblx0ICAgICAqIEBwcm9wZXJ0eSB7QXJyYXl9IHdvcmRzIFRoZSBhcnJheSBvZiAzMi1iaXQgd29yZHMuXG5cdCAgICAgKiBAcHJvcGVydHkge251bWJlcn0gc2lnQnl0ZXMgVGhlIG51bWJlciBvZiBzaWduaWZpY2FudCBieXRlcyBpbiB0aGlzIHdvcmQgYXJyYXkuXG5cdCAgICAgKi9cblx0ICAgIHZhciBXb3JkQXJyYXkgPSBDX2xpYi5Xb3JkQXJyYXkgPSBCYXNlLmV4dGVuZCh7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogSW5pdGlhbGl6ZXMgYSBuZXdseSBjcmVhdGVkIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0FycmF5fSB3b3JkcyAoT3B0aW9uYWwpIEFuIGFycmF5IG9mIDMyLWJpdCB3b3Jkcy5cblx0ICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gc2lnQnl0ZXMgKE9wdGlvbmFsKSBUaGUgbnVtYmVyIG9mIHNpZ25pZmljYW50IGJ5dGVzIGluIHRoZSB3b3Jkcy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIHdvcmRBcnJheSA9IENyeXB0b0pTLmxpYi5Xb3JkQXJyYXkuY3JlYXRlKCk7XG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5saWIuV29yZEFycmF5LmNyZWF0ZShbMHgwMDAxMDIwMywgMHgwNDA1MDYwN10pO1xuXHQgICAgICAgICAqICAgICB2YXIgd29yZEFycmF5ID0gQ3J5cHRvSlMubGliLldvcmRBcnJheS5jcmVhdGUoWzB4MDAwMTAyMDMsIDB4MDQwNTA2MDddLCA2KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBpbml0OiBmdW5jdGlvbiAod29yZHMsIHNpZ0J5dGVzKSB7XG5cdCAgICAgICAgICAgIHdvcmRzID0gdGhpcy53b3JkcyA9IHdvcmRzIHx8IFtdO1xuXG5cdCAgICAgICAgICAgIGlmIChzaWdCeXRlcyAhPSB1bmRlZmluZWQpIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMuc2lnQnl0ZXMgPSBzaWdCeXRlcztcblx0ICAgICAgICAgICAgfSBlbHNlIHtcblx0ICAgICAgICAgICAgICAgIHRoaXMuc2lnQnl0ZXMgPSB3b3Jkcy5sZW5ndGggKiA0O1xuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbnZlcnRzIHRoaXMgd29yZCBhcnJheSB0byBhIHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7RW5jb2Rlcn0gZW5jb2RlciAoT3B0aW9uYWwpIFRoZSBlbmNvZGluZyBzdHJhdGVneSB0byB1c2UuIERlZmF1bHQ6IENyeXB0b0pTLmVuYy5IZXhcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIHN0cmluZ2lmaWVkIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBzdHJpbmcgPSB3b3JkQXJyYXkgKyAnJztcblx0ICAgICAgICAgKiAgICAgdmFyIHN0cmluZyA9IHdvcmRBcnJheS50b1N0cmluZygpO1xuXHQgICAgICAgICAqICAgICB2YXIgc3RyaW5nID0gd29yZEFycmF5LnRvU3RyaW5nKENyeXB0b0pTLmVuYy5VdGY4KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICB0b1N0cmluZzogZnVuY3Rpb24gKGVuY29kZXIpIHtcblx0ICAgICAgICAgICAgcmV0dXJuIChlbmNvZGVyIHx8IEhleCkuc3RyaW5naWZ5KHRoaXMpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb25jYXRlbmF0ZXMgYSB3b3JkIGFycmF5IHRvIHRoaXMgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fSB3b3JkQXJyYXkgVGhlIHdvcmQgYXJyYXkgdG8gYXBwZW5kLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGlzIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHdvcmRBcnJheTEuY29uY2F0KHdvcmRBcnJheTIpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNvbmNhdDogZnVuY3Rpb24gKHdvcmRBcnJheSkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIHRoaXNXb3JkcyA9IHRoaXMud29yZHM7XG5cdCAgICAgICAgICAgIHZhciB0aGF0V29yZHMgPSB3b3JkQXJyYXkud29yZHM7XG5cdCAgICAgICAgICAgIHZhciB0aGlzU2lnQnl0ZXMgPSB0aGlzLnNpZ0J5dGVzO1xuXHQgICAgICAgICAgICB2YXIgdGhhdFNpZ0J5dGVzID0gd29yZEFycmF5LnNpZ0J5dGVzO1xuXG5cdCAgICAgICAgICAgIC8vIENsYW1wIGV4Y2VzcyBiaXRzXG5cdCAgICAgICAgICAgIHRoaXMuY2xhbXAoKTtcblxuXHQgICAgICAgICAgICAvLyBDb25jYXRcblx0ICAgICAgICAgICAgaWYgKHRoaXNTaWdCeXRlcyAlIDQpIHtcblx0ICAgICAgICAgICAgICAgIC8vIENvcHkgb25lIGJ5dGUgYXQgYSB0aW1lXG5cdCAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHRoYXRTaWdCeXRlczsgaSsrKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdmFyIHRoYXRCeXRlID0gKHRoYXRXb3Jkc1tpID4+PiAyXSA+Pj4gKDI0IC0gKGkgJSA0KSAqIDgpKSAmIDB4ZmY7XG5cdCAgICAgICAgICAgICAgICAgICAgdGhpc1dvcmRzWyh0aGlzU2lnQnl0ZXMgKyBpKSA+Pj4gMl0gfD0gdGhhdEJ5dGUgPDwgKDI0IC0gKCh0aGlzU2lnQnl0ZXMgKyBpKSAlIDQpICogOCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICAvLyBDb3B5IG9uZSB3b3JkIGF0IGEgdGltZVxuXHQgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCB0aGF0U2lnQnl0ZXM7IGkgKz0gNCkge1xuXHQgICAgICAgICAgICAgICAgICAgIHRoaXNXb3Jkc1sodGhpc1NpZ0J5dGVzICsgaSkgPj4+IDJdID0gdGhhdFdvcmRzW2kgPj4+IDJdO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cdCAgICAgICAgICAgIHRoaXMuc2lnQnl0ZXMgKz0gdGhhdFNpZ0J5dGVzO1xuXG5cdCAgICAgICAgICAgIC8vIENoYWluYWJsZVxuXHQgICAgICAgICAgICByZXR1cm4gdGhpcztcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogUmVtb3ZlcyBpbnNpZ25pZmljYW50IGJpdHMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHdvcmRBcnJheS5jbGFtcCgpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNsYW1wOiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSB0aGlzLndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgc2lnQnl0ZXMgPSB0aGlzLnNpZ0J5dGVzO1xuXG5cdCAgICAgICAgICAgIC8vIENsYW1wXG5cdCAgICAgICAgICAgIHdvcmRzW3NpZ0J5dGVzID4+PiAyXSAmPSAweGZmZmZmZmZmIDw8ICgzMiAtIChzaWdCeXRlcyAlIDQpICogOCk7XG5cdCAgICAgICAgICAgIHdvcmRzLmxlbmd0aCA9IE1hdGguY2VpbChzaWdCeXRlcyAvIDQpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDcmVhdGVzIGEgY29weSBvZiB0aGlzIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBjbG9uZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGNsb25lID0gd29yZEFycmF5LmNsb25lKCk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgY2xvbmU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgdmFyIGNsb25lID0gQmFzZS5jbG9uZS5jYWxsKHRoaXMpO1xuXHQgICAgICAgICAgICBjbG9uZS53b3JkcyA9IHRoaXMud29yZHMuc2xpY2UoMCk7XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGNsb25lO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDcmVhdGVzIGEgd29yZCBhcnJheSBmaWxsZWQgd2l0aCByYW5kb20gYnl0ZXMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge251bWJlcn0gbkJ5dGVzIFRoZSBudW1iZXIgb2YgcmFuZG9tIGJ5dGVzIHRvIGdlbmVyYXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgcmFuZG9tIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5saWIuV29yZEFycmF5LnJhbmRvbSgxNik7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgcmFuZG9tOiBmdW5jdGlvbiAobkJ5dGVzKSB7XG5cdCAgICAgICAgICAgIHZhciB3b3JkcyA9IFtdO1xuXG5cdCAgICAgICAgICAgIHZhciByID0gKGZ1bmN0aW9uIChtX3cpIHtcblx0ICAgICAgICAgICAgICAgIHZhciBtX3cgPSBtX3c7XG5cdCAgICAgICAgICAgICAgICB2YXIgbV96ID0gMHgzYWRlNjhiMTtcblx0ICAgICAgICAgICAgICAgIHZhciBtYXNrID0gMHhmZmZmZmZmZjtcblxuXHQgICAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgICAgICAgICBtX3ogPSAoMHg5MDY5ICogKG1feiAmIDB4RkZGRikgKyAobV96ID4+IDB4MTApKSAmIG1hc2s7XG5cdCAgICAgICAgICAgICAgICAgICAgbV93ID0gKDB4NDY1MCAqIChtX3cgJiAweEZGRkYpICsgKG1fdyA+PiAweDEwKSkgJiBtYXNrO1xuXHQgICAgICAgICAgICAgICAgICAgIHZhciByZXN1bHQgPSAoKG1feiA8PCAweDEwKSArIG1fdykgJiBtYXNrO1xuXHQgICAgICAgICAgICAgICAgICAgIHJlc3VsdCAvPSAweDEwMDAwMDAwMDtcblx0ICAgICAgICAgICAgICAgICAgICByZXN1bHQgKz0gMC41O1xuXHQgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQgKiAoTWF0aC5yYW5kb20oKSA+IC41ID8gMSA6IC0xKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfSk7XG5cblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIHJjYWNoZTsgaSA8IG5CeXRlczsgaSArPSA0KSB7XG5cdCAgICAgICAgICAgICAgICB2YXIgX3IgPSByKChyY2FjaGUgfHwgTWF0aC5yYW5kb20oKSkgKiAweDEwMDAwMDAwMCk7XG5cblx0ICAgICAgICAgICAgICAgIHJjYWNoZSA9IF9yKCkgKiAweDNhZGU2N2I3O1xuXHQgICAgICAgICAgICAgICAgd29yZHMucHVzaCgoX3IoKSAqIDB4MTAwMDAwMDAwKSB8IDApO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIG5ldyBXb3JkQXJyYXkuaW5pdCh3b3JkcywgbkJ5dGVzKTtcblx0ICAgICAgICB9XG5cdCAgICB9KTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBFbmNvZGVyIG5hbWVzcGFjZS5cblx0ICAgICAqL1xuXHQgICAgdmFyIENfZW5jID0gQy5lbmMgPSB7fTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBIZXggZW5jb2Rpbmcgc3RyYXRlZ3kuXG5cdCAgICAgKi9cblx0ICAgIHZhciBIZXggPSBDX2VuYy5IZXggPSB7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgYSB3b3JkIGFycmF5IHRvIGEgaGV4IHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fSB3b3JkQXJyYXkgVGhlIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtzdHJpbmd9IFRoZSBoZXggc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgaGV4U3RyaW5nID0gQ3J5cHRvSlMuZW5jLkhleC5zdHJpbmdpZnkod29yZEFycmF5KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBzdHJpbmdpZnk6IGZ1bmN0aW9uICh3b3JkQXJyYXkpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRzXG5cdCAgICAgICAgICAgIHZhciB3b3JkcyA9IHdvcmRBcnJheS53b3Jkcztcblx0ICAgICAgICAgICAgdmFyIHNpZ0J5dGVzID0gd29yZEFycmF5LnNpZ0J5dGVzO1xuXG5cdCAgICAgICAgICAgIC8vIENvbnZlcnRcblx0ICAgICAgICAgICAgdmFyIGhleENoYXJzID0gW107XG5cdCAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc2lnQnl0ZXM7IGkrKykge1xuXHQgICAgICAgICAgICAgICAgdmFyIGJpdGUgPSAod29yZHNbaSA+Pj4gMl0gPj4+ICgyNCAtIChpICUgNCkgKiA4KSkgJiAweGZmO1xuXHQgICAgICAgICAgICAgICAgaGV4Q2hhcnMucHVzaCgoYml0ZSA+Pj4gNCkudG9TdHJpbmcoMTYpKTtcblx0ICAgICAgICAgICAgICAgIGhleENoYXJzLnB1c2goKGJpdGUgJiAweDBmKS50b1N0cmluZygxNikpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGhleENoYXJzLmpvaW4oJycpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIGhleCBzdHJpbmcgdG8gYSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtzdHJpbmd9IGhleFN0ciBUaGUgaGV4IHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciB3b3JkQXJyYXkgPSBDcnlwdG9KUy5lbmMuSGV4LnBhcnNlKGhleFN0cmluZyk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgcGFyc2U6IGZ1bmN0aW9uIChoZXhTdHIpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRcblx0ICAgICAgICAgICAgdmFyIGhleFN0ckxlbmd0aCA9IGhleFN0ci5sZW5ndGg7XG5cblx0ICAgICAgICAgICAgLy8gQ29udmVydFxuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSBbXTtcblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoZXhTdHJMZW5ndGg7IGkgKz0gMikge1xuXHQgICAgICAgICAgICAgICAgd29yZHNbaSA+Pj4gM10gfD0gcGFyc2VJbnQoaGV4U3RyLnN1YnN0cihpLCAyKSwgMTYpIDw8ICgyNCAtIChpICUgOCkgKiA0KTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIHJldHVybiBuZXcgV29yZEFycmF5LmluaXQod29yZHMsIGhleFN0ckxlbmd0aCAvIDIpO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cblx0ICAgIC8qKlxuXHQgICAgICogTGF0aW4xIGVuY29kaW5nIHN0cmF0ZWd5LlxuXHQgICAgICovXG5cdCAgICB2YXIgTGF0aW4xID0gQ19lbmMuTGF0aW4xID0ge1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbnZlcnRzIGEgd29yZCBhcnJheSB0byBhIExhdGluMSBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheX0gd29yZEFycmF5IFRoZSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgTGF0aW4xIHN0cmluZy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGxhdGluMVN0cmluZyA9IENyeXB0b0pTLmVuYy5MYXRpbjEuc3RyaW5naWZ5KHdvcmRBcnJheSk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgc3RyaW5naWZ5OiBmdW5jdGlvbiAod29yZEFycmF5KSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgd29yZHMgPSB3b3JkQXJyYXkud29yZHM7XG5cdCAgICAgICAgICAgIHZhciBzaWdCeXRlcyA9IHdvcmRBcnJheS5zaWdCeXRlcztcblxuXHQgICAgICAgICAgICAvLyBDb252ZXJ0XG5cdCAgICAgICAgICAgIHZhciBsYXRpbjFDaGFycyA9IFtdO1xuXHQgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHNpZ0J5dGVzOyBpKyspIHtcblx0ICAgICAgICAgICAgICAgIHZhciBiaXRlID0gKHdvcmRzW2kgPj4+IDJdID4+PiAoMjQgLSAoaSAlIDQpICogOCkpICYgMHhmZjtcblx0ICAgICAgICAgICAgICAgIGxhdGluMUNoYXJzLnB1c2goU3RyaW5nLmZyb21DaGFyQ29kZShiaXRlKSk7XG5cdCAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICByZXR1cm4gbGF0aW4xQ2hhcnMuam9pbignJyk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbnZlcnRzIGEgTGF0aW4xIHN0cmluZyB0byBhIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGF0aW4xU3RyIFRoZSBMYXRpbjEgc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIHdvcmRBcnJheSA9IENyeXB0b0pTLmVuYy5MYXRpbjEucGFyc2UobGF0aW4xU3RyaW5nKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBwYXJzZTogZnVuY3Rpb24gKGxhdGluMVN0cikge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dFxuXHQgICAgICAgICAgICB2YXIgbGF0aW4xU3RyTGVuZ3RoID0gbGF0aW4xU3RyLmxlbmd0aDtcblxuXHQgICAgICAgICAgICAvLyBDb252ZXJ0XG5cdCAgICAgICAgICAgIHZhciB3b3JkcyA9IFtdO1xuXHQgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxhdGluMVN0ckxlbmd0aDsgaSsrKSB7XG5cdCAgICAgICAgICAgICAgICB3b3Jkc1tpID4+PiAyXSB8PSAobGF0aW4xU3RyLmNoYXJDb2RlQXQoaSkgJiAweGZmKSA8PCAoMjQgLSAoaSAlIDQpICogOCk7XG5cdCAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICByZXR1cm4gbmV3IFdvcmRBcnJheS5pbml0KHdvcmRzLCBsYXRpbjFTdHJMZW5ndGgpO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cblx0ICAgIC8qKlxuXHQgICAgICogVVRGLTggZW5jb2Rpbmcgc3RyYXRlZ3kuXG5cdCAgICAgKi9cblx0ICAgIHZhciBVdGY4ID0gQ19lbmMuVXRmOCA9IHtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIHdvcmQgYXJyYXkgdG8gYSBVVEYtOCBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheX0gd29yZEFycmF5IFRoZSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7c3RyaW5nfSBUaGUgVVRGLTggc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgdXRmOFN0cmluZyA9IENyeXB0b0pTLmVuYy5VdGY4LnN0cmluZ2lmeSh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHN0cmluZ2lmeTogZnVuY3Rpb24gKHdvcmRBcnJheSkge1xuXHQgICAgICAgICAgICB0cnkge1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIGRlY29kZVVSSUNvbXBvbmVudChlc2NhcGUoTGF0aW4xLnN0cmluZ2lmeSh3b3JkQXJyYXkpKSk7XG5cdCAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcblx0ICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignTWFsZm9ybWVkIFVURi04IGRhdGEnKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIFVURi04IHN0cmluZyB0byBhIHdvcmQgYXJyYXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge3N0cmluZ30gdXRmOFN0ciBUaGUgVVRGLTggc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIHdvcmRBcnJheSA9IENyeXB0b0pTLmVuYy5VdGY4LnBhcnNlKHV0ZjhTdHJpbmcpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHBhcnNlOiBmdW5jdGlvbiAodXRmOFN0cikge1xuXHQgICAgICAgICAgICByZXR1cm4gTGF0aW4xLnBhcnNlKHVuZXNjYXBlKGVuY29kZVVSSUNvbXBvbmVudCh1dGY4U3RyKSkpO1xuXHQgICAgICAgIH1cblx0ICAgIH07XG5cblx0ICAgIC8qKlxuXHQgICAgICogQWJzdHJhY3QgYnVmZmVyZWQgYmxvY2sgYWxnb3JpdGhtIHRlbXBsYXRlLlxuXHQgICAgICpcblx0ICAgICAqIFRoZSBwcm9wZXJ0eSBibG9ja1NpemUgbXVzdCBiZSBpbXBsZW1lbnRlZCBpbiBhIGNvbmNyZXRlIHN1YnR5cGUuXG5cdCAgICAgKlxuXHQgICAgICogQHByb3BlcnR5IHtudW1iZXJ9IF9taW5CdWZmZXJTaXplIFRoZSBudW1iZXIgb2YgYmxvY2tzIHRoYXQgc2hvdWxkIGJlIGtlcHQgdW5wcm9jZXNzZWQgaW4gdGhlIGJ1ZmZlci4gRGVmYXVsdDogMFxuXHQgICAgICovXG5cdCAgICB2YXIgQnVmZmVyZWRCbG9ja0FsZ29yaXRobSA9IENfbGliLkJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0gPSBCYXNlLmV4dGVuZCh7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogUmVzZXRzIHRoaXMgYmxvY2sgYWxnb3JpdGhtJ3MgZGF0YSBidWZmZXIgdG8gaXRzIGluaXRpYWwgc3RhdGUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0ucmVzZXQoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBJbml0aWFsIHZhbHVlc1xuXHQgICAgICAgICAgICB0aGlzLl9kYXRhID0gbmV3IFdvcmRBcnJheS5pbml0KCk7XG5cdCAgICAgICAgICAgIHRoaXMuX25EYXRhQnl0ZXMgPSAwO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBBZGRzIG5ldyBkYXRhIHRvIHRoaXMgYmxvY2sgYWxnb3JpdGhtJ3MgYnVmZmVyLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBkYXRhIFRoZSBkYXRhIHRvIGFwcGVuZC4gU3RyaW5ncyBhcmUgY29udmVydGVkIHRvIGEgV29yZEFycmF5IHVzaW5nIFVURi04LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICBidWZmZXJlZEJsb2NrQWxnb3JpdGhtLl9hcHBlbmQoJ2RhdGEnKTtcblx0ICAgICAgICAgKiAgICAgYnVmZmVyZWRCbG9ja0FsZ29yaXRobS5fYXBwZW5kKHdvcmRBcnJheSk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgX2FwcGVuZDogZnVuY3Rpb24gKGRhdGEpIHtcblx0ICAgICAgICAgICAgLy8gQ29udmVydCBzdHJpbmcgdG8gV29yZEFycmF5LCBlbHNlIGFzc3VtZSBXb3JkQXJyYXkgYWxyZWFkeVxuXHQgICAgICAgICAgICBpZiAodHlwZW9mIGRhdGEgPT0gJ3N0cmluZycpIHtcblx0ICAgICAgICAgICAgICAgIGRhdGEgPSBVdGY4LnBhcnNlKGRhdGEpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gQXBwZW5kXG5cdCAgICAgICAgICAgIHRoaXMuX2RhdGEuY29uY2F0KGRhdGEpO1xuXHQgICAgICAgICAgICB0aGlzLl9uRGF0YUJ5dGVzICs9IGRhdGEuc2lnQnl0ZXM7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFByb2Nlc3NlcyBhdmFpbGFibGUgZGF0YSBibG9ja3MuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBUaGlzIG1ldGhvZCBpbnZva2VzIF9kb1Byb2Nlc3NCbG9jayhvZmZzZXQpLCB3aGljaCBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IGEgY29uY3JldGUgc3VidHlwZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZG9GbHVzaCBXaGV0aGVyIGFsbCBibG9ja3MgYW5kIHBhcnRpYWwgYmxvY2tzIHNob3VsZCBiZSBwcm9jZXNzZWQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBwcm9jZXNzZWQgZGF0YS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIHByb2Nlc3NlZERhdGEgPSBidWZmZXJlZEJsb2NrQWxnb3JpdGhtLl9wcm9jZXNzKCk7XG5cdCAgICAgICAgICogICAgIHZhciBwcm9jZXNzZWREYXRhID0gYnVmZmVyZWRCbG9ja0FsZ29yaXRobS5fcHJvY2VzcyghISdmbHVzaCcpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIF9wcm9jZXNzOiBmdW5jdGlvbiAoZG9GbHVzaCkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9kYXRhO1xuXHQgICAgICAgICAgICB2YXIgZGF0YVdvcmRzID0gZGF0YS53b3Jkcztcblx0ICAgICAgICAgICAgdmFyIGRhdGFTaWdCeXRlcyA9IGRhdGEuc2lnQnl0ZXM7XG5cdCAgICAgICAgICAgIHZhciBibG9ja1NpemUgPSB0aGlzLmJsb2NrU2l6ZTtcblx0ICAgICAgICAgICAgdmFyIGJsb2NrU2l6ZUJ5dGVzID0gYmxvY2tTaXplICogNDtcblxuXHQgICAgICAgICAgICAvLyBDb3VudCBibG9ja3MgcmVhZHlcblx0ICAgICAgICAgICAgdmFyIG5CbG9ja3NSZWFkeSA9IGRhdGFTaWdCeXRlcyAvIGJsb2NrU2l6ZUJ5dGVzO1xuXHQgICAgICAgICAgICBpZiAoZG9GbHVzaCkge1xuXHQgICAgICAgICAgICAgICAgLy8gUm91bmQgdXAgdG8gaW5jbHVkZSBwYXJ0aWFsIGJsb2Nrc1xuXHQgICAgICAgICAgICAgICAgbkJsb2Nrc1JlYWR5ID0gTWF0aC5jZWlsKG5CbG9ja3NSZWFkeSk7XG5cdCAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICAvLyBSb3VuZCBkb3duIHRvIGluY2x1ZGUgb25seSBmdWxsIGJsb2Nrcyxcblx0ICAgICAgICAgICAgICAgIC8vIGxlc3MgdGhlIG51bWJlciBvZiBibG9ja3MgdGhhdCBtdXN0IHJlbWFpbiBpbiB0aGUgYnVmZmVyXG5cdCAgICAgICAgICAgICAgICBuQmxvY2tzUmVhZHkgPSBNYXRoLm1heCgobkJsb2Nrc1JlYWR5IHwgMCkgLSB0aGlzLl9taW5CdWZmZXJTaXplLCAwKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIENvdW50IHdvcmRzIHJlYWR5XG5cdCAgICAgICAgICAgIHZhciBuV29yZHNSZWFkeSA9IG5CbG9ja3NSZWFkeSAqIGJsb2NrU2l6ZTtcblxuXHQgICAgICAgICAgICAvLyBDb3VudCBieXRlcyByZWFkeVxuXHQgICAgICAgICAgICB2YXIgbkJ5dGVzUmVhZHkgPSBNYXRoLm1pbihuV29yZHNSZWFkeSAqIDQsIGRhdGFTaWdCeXRlcyk7XG5cblx0ICAgICAgICAgICAgLy8gUHJvY2VzcyBibG9ja3Ncblx0ICAgICAgICAgICAgaWYgKG5Xb3Jkc1JlYWR5KSB7XG5cdCAgICAgICAgICAgICAgICBmb3IgKHZhciBvZmZzZXQgPSAwOyBvZmZzZXQgPCBuV29yZHNSZWFkeTsgb2Zmc2V0ICs9IGJsb2NrU2l6ZSkge1xuXHQgICAgICAgICAgICAgICAgICAgIC8vIFBlcmZvcm0gY29uY3JldGUtYWxnb3JpdGhtIGxvZ2ljXG5cdCAgICAgICAgICAgICAgICAgICAgdGhpcy5fZG9Qcm9jZXNzQmxvY2soZGF0YVdvcmRzLCBvZmZzZXQpO1xuXHQgICAgICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgICAgICAvLyBSZW1vdmUgcHJvY2Vzc2VkIHdvcmRzXG5cdCAgICAgICAgICAgICAgICB2YXIgcHJvY2Vzc2VkV29yZHMgPSBkYXRhV29yZHMuc3BsaWNlKDAsIG5Xb3Jkc1JlYWR5KTtcblx0ICAgICAgICAgICAgICAgIGRhdGEuc2lnQnl0ZXMgLT0gbkJ5dGVzUmVhZHk7XG5cdCAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICAvLyBSZXR1cm4gcHJvY2Vzc2VkIHdvcmRzXG5cdCAgICAgICAgICAgIHJldHVybiBuZXcgV29yZEFycmF5LmluaXQocHJvY2Vzc2VkV29yZHMsIG5CeXRlc1JlYWR5KTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyBhIGNvcHkgb2YgdGhpcyBvYmplY3QuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtPYmplY3R9IFRoZSBjbG9uZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGNsb25lID0gYnVmZmVyZWRCbG9ja0FsZ29yaXRobS5jbG9uZSgpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNsb25lOiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIHZhciBjbG9uZSA9IEJhc2UuY2xvbmUuY2FsbCh0aGlzKTtcblx0ICAgICAgICAgICAgY2xvbmUuX2RhdGEgPSB0aGlzLl9kYXRhLmNsb25lKCk7XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGNsb25lO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICBfbWluQnVmZmVyU2l6ZTogMFxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogQWJzdHJhY3QgaGFzaGVyIHRlbXBsYXRlLlxuXHQgICAgICpcblx0ICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBibG9ja1NpemUgVGhlIG51bWJlciBvZiAzMi1iaXQgd29yZHMgdGhpcyBoYXNoZXIgb3BlcmF0ZXMgb24uIERlZmF1bHQ6IDE2ICg1MTIgYml0cylcblx0ICAgICAqL1xuXHQgICAgdmFyIEhhc2hlciA9IENfbGliLkhhc2hlciA9IEJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0uZXh0ZW5kKHtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb25maWd1cmF0aW9uIG9wdGlvbnMuXG5cdCAgICAgICAgICovXG5cdCAgICAgICAgY2ZnOiBCYXNlLmV4dGVuZCgpLFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogSW5pdGlhbGl6ZXMgYSBuZXdseSBjcmVhdGVkIGhhc2hlci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7T2JqZWN0fSBjZmcgKE9wdGlvbmFsKSBUaGUgY29uZmlndXJhdGlvbiBvcHRpb25zIHRvIHVzZSBmb3IgdGhpcyBoYXNoIGNvbXB1dGF0aW9uLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgaGFzaGVyID0gQ3J5cHRvSlMuYWxnby5TSEEyNTYuY3JlYXRlKCk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgaW5pdDogZnVuY3Rpb24gKGNmZykge1xuXHQgICAgICAgICAgICAvLyBBcHBseSBjb25maWcgZGVmYXVsdHNcblx0ICAgICAgICAgICAgdGhpcy5jZmcgPSB0aGlzLmNmZy5leHRlbmQoY2ZnKTtcblxuXHQgICAgICAgICAgICAvLyBTZXQgaW5pdGlhbCB2YWx1ZXNcblx0ICAgICAgICAgICAgdGhpcy5yZXNldCgpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBSZXNldHMgdGhpcyBoYXNoZXIgdG8gaXRzIGluaXRpYWwgc3RhdGUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGhhc2hlci5yZXNldCgpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHJlc2V0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIC8vIFJlc2V0IGRhdGEgYnVmZmVyXG5cdCAgICAgICAgICAgIEJ1ZmZlcmVkQmxvY2tBbGdvcml0aG0ucmVzZXQuY2FsbCh0aGlzKTtcblxuXHQgICAgICAgICAgICAvLyBQZXJmb3JtIGNvbmNyZXRlLWhhc2hlciBsb2dpY1xuXHQgICAgICAgICAgICB0aGlzLl9kb1Jlc2V0KCk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFVwZGF0ZXMgdGhpcyBoYXNoZXIgd2l0aCBhIG1lc3NhZ2UuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2VVcGRhdGUgVGhlIG1lc3NhZ2UgdG8gYXBwZW5kLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7SGFzaGVyfSBUaGlzIGhhc2hlci5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgaGFzaGVyLnVwZGF0ZSgnbWVzc2FnZScpO1xuXHQgICAgICAgICAqICAgICBoYXNoZXIudXBkYXRlKHdvcmRBcnJheSk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdXBkYXRlOiBmdW5jdGlvbiAobWVzc2FnZVVwZGF0ZSkge1xuXHQgICAgICAgICAgICAvLyBBcHBlbmRcblx0ICAgICAgICAgICAgdGhpcy5fYXBwZW5kKG1lc3NhZ2VVcGRhdGUpO1xuXG5cdCAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgaGFzaFxuXHQgICAgICAgICAgICB0aGlzLl9wcm9jZXNzKCk7XG5cblx0ICAgICAgICAgICAgLy8gQ2hhaW5hYmxlXG5cdCAgICAgICAgICAgIHJldHVybiB0aGlzO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBGaW5hbGl6ZXMgdGhlIGhhc2ggY29tcHV0YXRpb24uXG5cdCAgICAgICAgICogTm90ZSB0aGF0IHRoZSBmaW5hbGl6ZSBvcGVyYXRpb24gaXMgZWZmZWN0aXZlbHkgYSBkZXN0cnVjdGl2ZSwgcmVhZC1vbmNlIG9wZXJhdGlvbi5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30gbWVzc2FnZVVwZGF0ZSAoT3B0aW9uYWwpIEEgZmluYWwgbWVzc2FnZSB1cGRhdGUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBoYXNoLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgaGFzaCA9IGhhc2hlci5maW5hbGl6ZSgpO1xuXHQgICAgICAgICAqICAgICB2YXIgaGFzaCA9IGhhc2hlci5maW5hbGl6ZSgnbWVzc2FnZScpO1xuXHQgICAgICAgICAqICAgICB2YXIgaGFzaCA9IGhhc2hlci5maW5hbGl6ZSh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGZpbmFsaXplOiBmdW5jdGlvbiAobWVzc2FnZVVwZGF0ZSkge1xuXHQgICAgICAgICAgICAvLyBGaW5hbCBtZXNzYWdlIHVwZGF0ZVxuXHQgICAgICAgICAgICBpZiAobWVzc2FnZVVwZGF0ZSkge1xuXHQgICAgICAgICAgICAgICAgdGhpcy5fYXBwZW5kKG1lc3NhZ2VVcGRhdGUpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gUGVyZm9ybSBjb25jcmV0ZS1oYXNoZXIgbG9naWNcblx0ICAgICAgICAgICAgdmFyIGhhc2ggPSB0aGlzLl9kb0ZpbmFsaXplKCk7XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGhhc2g7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIGJsb2NrU2l6ZTogNTEyLzMyLFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ3JlYXRlcyBhIHNob3J0Y3V0IGZ1bmN0aW9uIHRvIGEgaGFzaGVyJ3Mgb2JqZWN0IGludGVyZmFjZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7SGFzaGVyfSBoYXNoZXIgVGhlIGhhc2hlciB0byBjcmVhdGUgYSBoZWxwZXIgZm9yLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSBzaG9ydGN1dCBmdW5jdGlvbi5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIFNIQTI1NiA9IENyeXB0b0pTLmxpYi5IYXNoZXIuX2NyZWF0ZUhlbHBlcihDcnlwdG9KUy5hbGdvLlNIQTI1Nik7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgX2NyZWF0ZUhlbHBlcjogZnVuY3Rpb24gKGhhc2hlcikge1xuXHQgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKG1lc3NhZ2UsIGNmZykge1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBoYXNoZXIuaW5pdChjZmcpLmZpbmFsaXplKG1lc3NhZ2UpO1xuXHQgICAgICAgICAgICB9O1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDcmVhdGVzIGEgc2hvcnRjdXQgZnVuY3Rpb24gdG8gdGhlIEhNQUMncyBvYmplY3QgaW50ZXJmYWNlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtIYXNoZXJ9IGhhc2hlciBUaGUgaGFzaGVyIHRvIHVzZSBpbiB0aGlzIEhNQUMgaGVscGVyLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7RnVuY3Rpb259IFRoZSBzaG9ydGN1dCBmdW5jdGlvbi5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBzdGF0aWNcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIEhtYWNTSEEyNTYgPSBDcnlwdG9KUy5saWIuSGFzaGVyLl9jcmVhdGVIbWFjSGVscGVyKENyeXB0b0pTLmFsZ28uU0hBMjU2KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBfY3JlYXRlSG1hY0hlbHBlcjogZnVuY3Rpb24gKGhhc2hlcikge1xuXHQgICAgICAgICAgICByZXR1cm4gZnVuY3Rpb24gKG1lc3NhZ2UsIGtleSkge1xuXHQgICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBDX2FsZ28uSE1BQy5pbml0KGhhc2hlciwga2V5KS5maW5hbGl6ZShtZXNzYWdlKTtcblx0ICAgICAgICAgICAgfTtcblx0ICAgICAgICB9XG5cdCAgICB9KTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBBbGdvcml0aG0gbmFtZXNwYWNlLlxuXHQgICAgICovXG5cdCAgICB2YXIgQ19hbGdvID0gQy5hbGdvID0ge307XG5cblx0ICAgIHJldHVybiBDO1xuXHR9KE1hdGgpKTtcblxuXG5cdHJldHVybiBDcnlwdG9KUztcblxufSkpOyIsIjsoZnVuY3Rpb24gKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYgKHR5cGVvZiBleHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoXCIuL2NvcmVcIikpO1xuXHR9XG5cdGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKFtcIi4vY29yZVwiXSwgZmFjdG9yeSk7XG5cdH1cblx0ZWxzZSB7XG5cdFx0Ly8gR2xvYmFsIChicm93c2VyKVxuXHRcdGZhY3Rvcnkocm9vdC5DcnlwdG9KUyk7XG5cdH1cbn0odGhpcywgZnVuY3Rpb24gKENyeXB0b0pTKSB7XG5cblx0KGZ1bmN0aW9uICgpIHtcblx0ICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgdmFyIEMgPSBDcnlwdG9KUztcblx0ICAgIHZhciBDX2xpYiA9IEMubGliO1xuXHQgICAgdmFyIFdvcmRBcnJheSA9IENfbGliLldvcmRBcnJheTtcblx0ICAgIHZhciBDX2VuYyA9IEMuZW5jO1xuXG5cdCAgICAvKipcblx0ICAgICAqIEJhc2U2NCBlbmNvZGluZyBzdHJhdGVneS5cblx0ICAgICAqL1xuXHQgICAgdmFyIEJhc2U2NCA9IENfZW5jLkJhc2U2NCA9IHtcblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBDb252ZXJ0cyBhIHdvcmQgYXJyYXkgdG8gYSBCYXNlNjQgc3RyaW5nLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl9IHdvcmRBcnJheSBUaGUgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge3N0cmluZ30gVGhlIEJhc2U2NCBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAc3RhdGljXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBiYXNlNjRTdHJpbmcgPSBDcnlwdG9KUy5lbmMuQmFzZTY0LnN0cmluZ2lmeSh3b3JkQXJyYXkpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHN0cmluZ2lmeTogZnVuY3Rpb24gKHdvcmRBcnJheSkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIHdvcmRzID0gd29yZEFycmF5LndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgc2lnQnl0ZXMgPSB3b3JkQXJyYXkuc2lnQnl0ZXM7XG5cdCAgICAgICAgICAgIHZhciBtYXAgPSB0aGlzLl9tYXA7XG5cblx0ICAgICAgICAgICAgLy8gQ2xhbXAgZXhjZXNzIGJpdHNcblx0ICAgICAgICAgICAgd29yZEFycmF5LmNsYW1wKCk7XG5cblx0ICAgICAgICAgICAgLy8gQ29udmVydFxuXHQgICAgICAgICAgICB2YXIgYmFzZTY0Q2hhcnMgPSBbXTtcblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaWdCeXRlczsgaSArPSAzKSB7XG5cdCAgICAgICAgICAgICAgICB2YXIgYnl0ZTEgPSAod29yZHNbaSA+Pj4gMl0gICAgICAgPj4+ICgyNCAtIChpICUgNCkgKiA4KSkgICAgICAgJiAweGZmO1xuXHQgICAgICAgICAgICAgICAgdmFyIGJ5dGUyID0gKHdvcmRzWyhpICsgMSkgPj4+IDJdID4+PiAoMjQgLSAoKGkgKyAxKSAlIDQpICogOCkpICYgMHhmZjtcblx0ICAgICAgICAgICAgICAgIHZhciBieXRlMyA9ICh3b3Jkc1soaSArIDIpID4+PiAyXSA+Pj4gKDI0IC0gKChpICsgMikgJSA0KSAqIDgpKSAmIDB4ZmY7XG5cblx0ICAgICAgICAgICAgICAgIHZhciB0cmlwbGV0ID0gKGJ5dGUxIDw8IDE2KSB8IChieXRlMiA8PCA4KSB8IGJ5dGUzO1xuXG5cdCAgICAgICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgKGogPCA0KSAmJiAoaSArIGogKiAwLjc1IDwgc2lnQnl0ZXMpOyBqKyspIHtcblx0ICAgICAgICAgICAgICAgICAgICBiYXNlNjRDaGFycy5wdXNoKG1hcC5jaGFyQXQoKHRyaXBsZXQgPj4+ICg2ICogKDMgLSBqKSkpICYgMHgzZikpO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gQWRkIHBhZGRpbmdcblx0ICAgICAgICAgICAgdmFyIHBhZGRpbmdDaGFyID0gbWFwLmNoYXJBdCg2NCk7XG5cdCAgICAgICAgICAgIGlmIChwYWRkaW5nQ2hhcikge1xuXHQgICAgICAgICAgICAgICAgd2hpbGUgKGJhc2U2NENoYXJzLmxlbmd0aCAlIDQpIHtcblx0ICAgICAgICAgICAgICAgICAgICBiYXNlNjRDaGFycy5wdXNoKHBhZGRpbmdDaGFyKTtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIHJldHVybiBiYXNlNjRDaGFycy5qb2luKCcnKTtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogQ29udmVydHMgYSBCYXNlNjQgc3RyaW5nIHRvIGEgd29yZCBhcnJheS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7c3RyaW5nfSBiYXNlNjRTdHIgVGhlIEJhc2U2NCBzdHJpbmcuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSB3b3JkIGFycmF5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHN0YXRpY1xuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIgd29yZEFycmF5ID0gQ3J5cHRvSlMuZW5jLkJhc2U2NC5wYXJzZShiYXNlNjRTdHJpbmcpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIHBhcnNlOiBmdW5jdGlvbiAoYmFzZTY0U3RyKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgYmFzZTY0U3RyTGVuZ3RoID0gYmFzZTY0U3RyLmxlbmd0aDtcblx0ICAgICAgICAgICAgdmFyIG1hcCA9IHRoaXMuX21hcDtcblx0ICAgICAgICAgICAgdmFyIHJldmVyc2VNYXAgPSB0aGlzLl9yZXZlcnNlTWFwO1xuXG5cdCAgICAgICAgICAgIGlmICghcmV2ZXJzZU1hcCkge1xuXHQgICAgICAgICAgICAgICAgICAgIHJldmVyc2VNYXAgPSB0aGlzLl9yZXZlcnNlTWFwID0gW107XG5cdCAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBtYXAubGVuZ3RoOyBqKyspIHtcblx0ICAgICAgICAgICAgICAgICAgICAgICAgcmV2ZXJzZU1hcFttYXAuY2hhckNvZGVBdChqKV0gPSBqO1xuXHQgICAgICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIElnbm9yZSBwYWRkaW5nXG5cdCAgICAgICAgICAgIHZhciBwYWRkaW5nQ2hhciA9IG1hcC5jaGFyQXQoNjQpO1xuXHQgICAgICAgICAgICBpZiAocGFkZGluZ0NoYXIpIHtcblx0ICAgICAgICAgICAgICAgIHZhciBwYWRkaW5nSW5kZXggPSBiYXNlNjRTdHIuaW5kZXhPZihwYWRkaW5nQ2hhcik7XG5cdCAgICAgICAgICAgICAgICBpZiAocGFkZGluZ0luZGV4ICE9PSAtMSkge1xuXHQgICAgICAgICAgICAgICAgICAgIGJhc2U2NFN0ckxlbmd0aCA9IHBhZGRpbmdJbmRleDtcblx0ICAgICAgICAgICAgICAgIH1cblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIENvbnZlcnRcblx0ICAgICAgICAgICAgcmV0dXJuIHBhcnNlTG9vcChiYXNlNjRTdHIsIGJhc2U2NFN0ckxlbmd0aCwgcmV2ZXJzZU1hcCk7XG5cblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgX21hcDogJ0FCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXowMTIzNDU2Nzg5Ky89J1xuXHQgICAgfTtcblxuXHQgICAgZnVuY3Rpb24gcGFyc2VMb29wKGJhc2U2NFN0ciwgYmFzZTY0U3RyTGVuZ3RoLCByZXZlcnNlTWFwKSB7XG5cdCAgICAgIHZhciB3b3JkcyA9IFtdO1xuXHQgICAgICB2YXIgbkJ5dGVzID0gMDtcblx0ICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBiYXNlNjRTdHJMZW5ndGg7IGkrKykge1xuXHQgICAgICAgICAgaWYgKGkgJSA0KSB7XG5cdCAgICAgICAgICAgICAgdmFyIGJpdHMxID0gcmV2ZXJzZU1hcFtiYXNlNjRTdHIuY2hhckNvZGVBdChpIC0gMSldIDw8ICgoaSAlIDQpICogMik7XG5cdCAgICAgICAgICAgICAgdmFyIGJpdHMyID0gcmV2ZXJzZU1hcFtiYXNlNjRTdHIuY2hhckNvZGVBdChpKV0gPj4+ICg2IC0gKGkgJSA0KSAqIDIpO1xuXHQgICAgICAgICAgICAgIHdvcmRzW25CeXRlcyA+Pj4gMl0gfD0gKGJpdHMxIHwgYml0czIpIDw8ICgyNCAtIChuQnl0ZXMgJSA0KSAqIDgpO1xuXHQgICAgICAgICAgICAgIG5CeXRlcysrO1xuXHQgICAgICAgICAgfVxuXHQgICAgICB9XG5cdCAgICAgIHJldHVybiBXb3JkQXJyYXkuY3JlYXRlKHdvcmRzLCBuQnl0ZXMpO1xuXHQgICAgfVxuXHR9KCkpO1xuXG5cblx0cmV0dXJuIENyeXB0b0pTLmVuYy5CYXNlNjQ7XG5cbn0pKTsiLCI7KGZ1bmN0aW9uIChyb290LCBmYWN0b3J5KSB7XG5cdGlmICh0eXBlb2YgZXhwb3J0cyA9PT0gXCJvYmplY3RcIikge1xuXHRcdC8vIENvbW1vbkpTXG5cdFx0bW9kdWxlLmV4cG9ydHMgPSBleHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwiLi9jb3JlXCIpKTtcblx0fVxuXHRlbHNlIGlmICh0eXBlb2YgZGVmaW5lID09PSBcImZ1bmN0aW9uXCIgJiYgZGVmaW5lLmFtZCkge1xuXHRcdC8vIEFNRFxuXHRcdGRlZmluZShbXCIuL2NvcmVcIl0sIGZhY3RvcnkpO1xuXHR9XG5cdGVsc2Uge1xuXHRcdC8vIEdsb2JhbCAoYnJvd3Nlcilcblx0XHRmYWN0b3J5KHJvb3QuQ3J5cHRvSlMpO1xuXHR9XG59KHRoaXMsIGZ1bmN0aW9uIChDcnlwdG9KUykge1xuXG5cdHJldHVybiBDcnlwdG9KUy5lbmMuSGV4O1xuXG59KSk7IiwiOyhmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSwgdW5kZWYpIHtcblx0aWYgKHR5cGVvZiBleHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoXCIuL2NvcmVcIiksIHJlcXVpcmUoXCIuL3NoYTFcIiksIHJlcXVpcmUoXCIuL2htYWNcIikpO1xuXHR9XG5cdGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKFtcIi4vY29yZVwiLCBcIi4vc2hhMVwiLCBcIi4vaG1hY1wiXSwgZmFjdG9yeSk7XG5cdH1cblx0ZWxzZSB7XG5cdFx0Ly8gR2xvYmFsIChicm93c2VyKVxuXHRcdGZhY3Rvcnkocm9vdC5DcnlwdG9KUyk7XG5cdH1cbn0odGhpcywgZnVuY3Rpb24gKENyeXB0b0pTKSB7XG5cblx0KGZ1bmN0aW9uICgpIHtcblx0ICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgdmFyIEMgPSBDcnlwdG9KUztcblx0ICAgIHZhciBDX2xpYiA9IEMubGliO1xuXHQgICAgdmFyIEJhc2UgPSBDX2xpYi5CYXNlO1xuXHQgICAgdmFyIFdvcmRBcnJheSA9IENfbGliLldvcmRBcnJheTtcblx0ICAgIHZhciBDX2FsZ28gPSBDLmFsZ287XG5cdCAgICB2YXIgTUQ1ID0gQ19hbGdvLk1ENTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBUaGlzIGtleSBkZXJpdmF0aW9uIGZ1bmN0aW9uIGlzIG1lYW50IHRvIGNvbmZvcm0gd2l0aCBFVlBfQnl0ZXNUb0tleS5cblx0ICAgICAqIHd3dy5vcGVuc3NsLm9yZy9kb2NzL2NyeXB0by9FVlBfQnl0ZXNUb0tleS5odG1sXG5cdCAgICAgKi9cblx0ICAgIHZhciBFdnBLREYgPSBDX2FsZ28uRXZwS0RGID0gQmFzZS5leHRlbmQoe1xuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIENvbmZpZ3VyYXRpb24gb3B0aW9ucy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwcm9wZXJ0eSB7bnVtYmVyfSBrZXlTaXplIFRoZSBrZXkgc2l6ZSBpbiB3b3JkcyB0byBnZW5lcmF0ZS4gRGVmYXVsdDogNCAoMTI4IGJpdHMpXG5cdCAgICAgICAgICogQHByb3BlcnR5IHtIYXNoZXJ9IGhhc2hlciBUaGUgaGFzaCBhbGdvcml0aG0gdG8gdXNlLiBEZWZhdWx0OiBNRDVcblx0ICAgICAgICAgKiBAcHJvcGVydHkge251bWJlcn0gaXRlcmF0aW9ucyBUaGUgbnVtYmVyIG9mIGl0ZXJhdGlvbnMgdG8gcGVyZm9ybS4gRGVmYXVsdDogMVxuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNmZzogQmFzZS5leHRlbmQoe1xuXHQgICAgICAgICAgICBrZXlTaXplOiAxMjgvMzIsXG5cdCAgICAgICAgICAgIGhhc2hlcjogTUQ1LFxuXHQgICAgICAgICAgICBpdGVyYXRpb25zOiAxXG5cdCAgICAgICAgfSksXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBJbml0aWFsaXplcyBhIG5ld2x5IGNyZWF0ZWQga2V5IGRlcml2YXRpb24gZnVuY3Rpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge09iamVjdH0gY2ZnIChPcHRpb25hbCkgVGhlIGNvbmZpZ3VyYXRpb24gb3B0aW9ucyB0byB1c2UgZm9yIHRoZSBkZXJpdmF0aW9uLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIga2RmID0gQ3J5cHRvSlMuYWxnby5FdnBLREYuY3JlYXRlKCk7XG5cdCAgICAgICAgICogICAgIHZhciBrZGYgPSBDcnlwdG9KUy5hbGdvLkV2cEtERi5jcmVhdGUoeyBrZXlTaXplOiA4IH0pO1xuXHQgICAgICAgICAqICAgICB2YXIga2RmID0gQ3J5cHRvSlMuYWxnby5FdnBLREYuY3JlYXRlKHsga2V5U2l6ZTogOCwgaXRlcmF0aW9uczogMTAwMCB9KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBpbml0OiBmdW5jdGlvbiAoY2ZnKSB7XG5cdCAgICAgICAgICAgIHRoaXMuY2ZnID0gdGhpcy5jZmcuZXh0ZW5kKGNmZyk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIERlcml2ZXMgYSBrZXkgZnJvbSBhIHBhc3N3b3JkLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBwYXNzd29yZCBUaGUgcGFzc3dvcmQuXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBzYWx0IEEgc2FsdC5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIGRlcml2ZWQga2V5LlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQGV4YW1wbGVcblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqICAgICB2YXIga2V5ID0ga2RmLmNvbXB1dGUocGFzc3dvcmQsIHNhbHQpO1xuXHQgICAgICAgICAqL1xuXHQgICAgICAgIGNvbXB1dGU6IGZ1bmN0aW9uIChwYXNzd29yZCwgc2FsdCkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dFxuXHQgICAgICAgICAgICB2YXIgY2ZnID0gdGhpcy5jZmc7XG5cblx0ICAgICAgICAgICAgLy8gSW5pdCBoYXNoZXJcblx0ICAgICAgICAgICAgdmFyIGhhc2hlciA9IGNmZy5oYXNoZXIuY3JlYXRlKCk7XG5cblx0ICAgICAgICAgICAgLy8gSW5pdGlhbCB2YWx1ZXNcblx0ICAgICAgICAgICAgdmFyIGRlcml2ZWRLZXkgPSBXb3JkQXJyYXkuY3JlYXRlKCk7XG5cblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRzXG5cdCAgICAgICAgICAgIHZhciBkZXJpdmVkS2V5V29yZHMgPSBkZXJpdmVkS2V5LndvcmRzO1xuXHQgICAgICAgICAgICB2YXIga2V5U2l6ZSA9IGNmZy5rZXlTaXplO1xuXHQgICAgICAgICAgICB2YXIgaXRlcmF0aW9ucyA9IGNmZy5pdGVyYXRpb25zO1xuXG5cdCAgICAgICAgICAgIC8vIEdlbmVyYXRlIGtleVxuXHQgICAgICAgICAgICB3aGlsZSAoZGVyaXZlZEtleVdvcmRzLmxlbmd0aCA8IGtleVNpemUpIHtcblx0ICAgICAgICAgICAgICAgIGlmIChibG9jaykge1xuXHQgICAgICAgICAgICAgICAgICAgIGhhc2hlci51cGRhdGUoYmxvY2spO1xuXHQgICAgICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICAgICAgdmFyIGJsb2NrID0gaGFzaGVyLnVwZGF0ZShwYXNzd29yZCkuZmluYWxpemUoc2FsdCk7XG5cdCAgICAgICAgICAgICAgICBoYXNoZXIucmVzZXQoKTtcblxuXHQgICAgICAgICAgICAgICAgLy8gSXRlcmF0aW9uc1xuXHQgICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBpdGVyYXRpb25zOyBpKyspIHtcblx0ICAgICAgICAgICAgICAgICAgICBibG9jayA9IGhhc2hlci5maW5hbGl6ZShibG9jayk7XG5cdCAgICAgICAgICAgICAgICAgICAgaGFzaGVyLnJlc2V0KCk7XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIGRlcml2ZWRLZXkuY29uY2F0KGJsb2NrKTtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBkZXJpdmVkS2V5LnNpZ0J5dGVzID0ga2V5U2l6ZSAqIDQ7XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGRlcml2ZWRLZXk7XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogRGVyaXZlcyBhIGtleSBmcm9tIGEgcGFzc3dvcmQuXG5cdCAgICAgKlxuXHQgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBwYXNzd29yZCBUaGUgcGFzc3dvcmQuXG5cdCAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IHNhbHQgQSBzYWx0LlxuXHQgICAgICogQHBhcmFtIHtPYmplY3R9IGNmZyAoT3B0aW9uYWwpIFRoZSBjb25maWd1cmF0aW9uIG9wdGlvbnMgdG8gdXNlIGZvciB0aGlzIGNvbXB1dGF0aW9uLlxuXHQgICAgICpcblx0ICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIGRlcml2ZWQga2V5LlxuXHQgICAgICpcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqICAgICB2YXIga2V5ID0gQ3J5cHRvSlMuRXZwS0RGKHBhc3N3b3JkLCBzYWx0KTtcblx0ICAgICAqICAgICB2YXIga2V5ID0gQ3J5cHRvSlMuRXZwS0RGKHBhc3N3b3JkLCBzYWx0LCB7IGtleVNpemU6IDggfSk7XG5cdCAgICAgKiAgICAgdmFyIGtleSA9IENyeXB0b0pTLkV2cEtERihwYXNzd29yZCwgc2FsdCwgeyBrZXlTaXplOiA4LCBpdGVyYXRpb25zOiAxMDAwIH0pO1xuXHQgICAgICovXG5cdCAgICBDLkV2cEtERiA9IGZ1bmN0aW9uIChwYXNzd29yZCwgc2FsdCwgY2ZnKSB7XG5cdCAgICAgICAgcmV0dXJuIEV2cEtERi5jcmVhdGUoY2ZnKS5jb21wdXRlKHBhc3N3b3JkLCBzYWx0KTtcblx0ICAgIH07XG5cdH0oKSk7XG5cblxuXHRyZXR1cm4gQ3J5cHRvSlMuRXZwS0RGO1xuXG59KSk7IiwiOyhmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuXHRpZiAodHlwZW9mIGV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcblx0XHQvLyBDb21tb25KU1xuXHRcdG1vZHVsZS5leHBvcnRzID0gZXhwb3J0cyA9IGZhY3RvcnkocmVxdWlyZShcIi4vY29yZVwiKSk7XG5cdH1cblx0ZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoW1wiLi9jb3JlXCJdLCBmYWN0b3J5KTtcblx0fVxuXHRlbHNlIHtcblx0XHQvLyBHbG9iYWwgKGJyb3dzZXIpXG5cdFx0ZmFjdG9yeShyb290LkNyeXB0b0pTKTtcblx0fVxufSh0aGlzLCBmdW5jdGlvbiAoQ3J5cHRvSlMpIHtcblxuXHQoZnVuY3Rpb24gKCkge1xuXHQgICAgLy8gU2hvcnRjdXRzXG5cdCAgICB2YXIgQyA9IENyeXB0b0pTO1xuXHQgICAgdmFyIENfbGliID0gQy5saWI7XG5cdCAgICB2YXIgQmFzZSA9IENfbGliLkJhc2U7XG5cdCAgICB2YXIgQ19lbmMgPSBDLmVuYztcblx0ICAgIHZhciBVdGY4ID0gQ19lbmMuVXRmODtcblx0ICAgIHZhciBDX2FsZ28gPSBDLmFsZ287XG5cblx0ICAgIC8qKlxuXHQgICAgICogSE1BQyBhbGdvcml0aG0uXG5cdCAgICAgKi9cblx0ICAgIHZhciBITUFDID0gQ19hbGdvLkhNQUMgPSBCYXNlLmV4dGVuZCh7XG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogSW5pdGlhbGl6ZXMgYSBuZXdseSBjcmVhdGVkIEhNQUMuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge0hhc2hlcn0gaGFzaGVyIFRoZSBoYXNoIGFsZ29yaXRobSB0byB1c2UuXG5cdCAgICAgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBrZXkgVGhlIHNlY3JldCBrZXkuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIHZhciBobWFjSGFzaGVyID0gQ3J5cHRvSlMuYWxnby5ITUFDLmNyZWF0ZShDcnlwdG9KUy5hbGdvLlNIQTI1Niwga2V5KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBpbml0OiBmdW5jdGlvbiAoaGFzaGVyLCBrZXkpIHtcblx0ICAgICAgICAgICAgLy8gSW5pdCBoYXNoZXJcblx0ICAgICAgICAgICAgaGFzaGVyID0gdGhpcy5faGFzaGVyID0gbmV3IGhhc2hlci5pbml0KCk7XG5cblx0ICAgICAgICAgICAgLy8gQ29udmVydCBzdHJpbmcgdG8gV29yZEFycmF5LCBlbHNlIGFzc3VtZSBXb3JkQXJyYXkgYWxyZWFkeVxuXHQgICAgICAgICAgICBpZiAodHlwZW9mIGtleSA9PSAnc3RyaW5nJykge1xuXHQgICAgICAgICAgICAgICAga2V5ID0gVXRmOC5wYXJzZShrZXkpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRzXG5cdCAgICAgICAgICAgIHZhciBoYXNoZXJCbG9ja1NpemUgPSBoYXNoZXIuYmxvY2tTaXplO1xuXHQgICAgICAgICAgICB2YXIgaGFzaGVyQmxvY2tTaXplQnl0ZXMgPSBoYXNoZXJCbG9ja1NpemUgKiA0O1xuXG5cdCAgICAgICAgICAgIC8vIEFsbG93IGFyYml0cmFyeSBsZW5ndGgga2V5c1xuXHQgICAgICAgICAgICBpZiAoa2V5LnNpZ0J5dGVzID4gaGFzaGVyQmxvY2tTaXplQnl0ZXMpIHtcblx0ICAgICAgICAgICAgICAgIGtleSA9IGhhc2hlci5maW5hbGl6ZShrZXkpO1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gQ2xhbXAgZXhjZXNzIGJpdHNcblx0ICAgICAgICAgICAga2V5LmNsYW1wKCk7XG5cblx0ICAgICAgICAgICAgLy8gQ2xvbmUga2V5IGZvciBpbm5lciBhbmQgb3V0ZXIgcGFkc1xuXHQgICAgICAgICAgICB2YXIgb0tleSA9IHRoaXMuX29LZXkgPSBrZXkuY2xvbmUoKTtcblx0ICAgICAgICAgICAgdmFyIGlLZXkgPSB0aGlzLl9pS2V5ID0ga2V5LmNsb25lKCk7XG5cblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRzXG5cdCAgICAgICAgICAgIHZhciBvS2V5V29yZHMgPSBvS2V5LndvcmRzO1xuXHQgICAgICAgICAgICB2YXIgaUtleVdvcmRzID0gaUtleS53b3JkcztcblxuXHQgICAgICAgICAgICAvLyBYT1Iga2V5cyB3aXRoIHBhZCBjb25zdGFudHNcblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBoYXNoZXJCbG9ja1NpemU7IGkrKykge1xuXHQgICAgICAgICAgICAgICAgb0tleVdvcmRzW2ldIF49IDB4NWM1YzVjNWM7XG5cdCAgICAgICAgICAgICAgICBpS2V5V29yZHNbaV0gXj0gMHgzNjM2MzYzNjtcblx0ICAgICAgICAgICAgfVxuXHQgICAgICAgICAgICBvS2V5LnNpZ0J5dGVzID0gaUtleS5zaWdCeXRlcyA9IGhhc2hlckJsb2NrU2l6ZUJ5dGVzO1xuXG5cdCAgICAgICAgICAgIC8vIFNldCBpbml0aWFsIHZhbHVlc1xuXHQgICAgICAgICAgICB0aGlzLnJlc2V0KCk7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIC8qKlxuXHQgICAgICAgICAqIFJlc2V0cyB0aGlzIEhNQUMgdG8gaXRzIGluaXRpYWwgc3RhdGUuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGhtYWNIYXNoZXIucmVzZXQoKTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICByZXNldDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dFxuXHQgICAgICAgICAgICB2YXIgaGFzaGVyID0gdGhpcy5faGFzaGVyO1xuXG5cdCAgICAgICAgICAgIC8vIFJlc2V0XG5cdCAgICAgICAgICAgIGhhc2hlci5yZXNldCgpO1xuXHQgICAgICAgICAgICBoYXNoZXIudXBkYXRlKHRoaXMuX2lLZXkpO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICAvKipcblx0ICAgICAgICAgKiBVcGRhdGVzIHRoaXMgSE1BQyB3aXRoIGEgbWVzc2FnZS5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30gbWVzc2FnZVVwZGF0ZSBUaGUgbWVzc2FnZSB0byBhcHBlbmQuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcmV0dXJuIHtITUFDfSBUaGlzIEhNQUMgaW5zdGFuY2UuXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAZXhhbXBsZVxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogICAgIGhtYWNIYXNoZXIudXBkYXRlKCdtZXNzYWdlJyk7XG5cdCAgICAgICAgICogICAgIGhtYWNIYXNoZXIudXBkYXRlKHdvcmRBcnJheSk7XG5cdCAgICAgICAgICovXG5cdCAgICAgICAgdXBkYXRlOiBmdW5jdGlvbiAobWVzc2FnZVVwZGF0ZSkge1xuXHQgICAgICAgICAgICB0aGlzLl9oYXNoZXIudXBkYXRlKG1lc3NhZ2VVcGRhdGUpO1xuXG5cdCAgICAgICAgICAgIC8vIENoYWluYWJsZVxuXHQgICAgICAgICAgICByZXR1cm4gdGhpcztcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgLyoqXG5cdCAgICAgICAgICogRmluYWxpemVzIHRoZSBITUFDIGNvbXB1dGF0aW9uLlxuXHQgICAgICAgICAqIE5vdGUgdGhhdCB0aGUgZmluYWxpemUgb3BlcmF0aW9uIGlzIGVmZmVjdGl2ZWx5IGEgZGVzdHJ1Y3RpdmUsIHJlYWQtb25jZSBvcGVyYXRpb24uXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2VVcGRhdGUgKE9wdGlvbmFsKSBBIGZpbmFsIG1lc3NhZ2UgdXBkYXRlLlxuXHQgICAgICAgICAqXG5cdCAgICAgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgSE1BQy5cblx0ICAgICAgICAgKlxuXHQgICAgICAgICAqIEBleGFtcGxlXG5cdCAgICAgICAgICpcblx0ICAgICAgICAgKiAgICAgdmFyIGhtYWMgPSBobWFjSGFzaGVyLmZpbmFsaXplKCk7XG5cdCAgICAgICAgICogICAgIHZhciBobWFjID0gaG1hY0hhc2hlci5maW5hbGl6ZSgnbWVzc2FnZScpO1xuXHQgICAgICAgICAqICAgICB2YXIgaG1hYyA9IGhtYWNIYXNoZXIuZmluYWxpemUod29yZEFycmF5KTtcblx0ICAgICAgICAgKi9cblx0ICAgICAgICBmaW5hbGl6ZTogZnVuY3Rpb24gKG1lc3NhZ2VVcGRhdGUpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRcblx0ICAgICAgICAgICAgdmFyIGhhc2hlciA9IHRoaXMuX2hhc2hlcjtcblxuXHQgICAgICAgICAgICAvLyBDb21wdXRlIEhNQUNcblx0ICAgICAgICAgICAgdmFyIGlubmVySGFzaCA9IGhhc2hlci5maW5hbGl6ZShtZXNzYWdlVXBkYXRlKTtcblx0ICAgICAgICAgICAgaGFzaGVyLnJlc2V0KCk7XG5cdCAgICAgICAgICAgIHZhciBobWFjID0gaGFzaGVyLmZpbmFsaXplKHRoaXMuX29LZXkuY2xvbmUoKS5jb25jYXQoaW5uZXJIYXNoKSk7XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGhtYWM7XG5cdCAgICAgICAgfVxuXHQgICAgfSk7XG5cdH0oKSk7XG5cblxufSkpOyIsIjsoZnVuY3Rpb24gKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYgKHR5cGVvZiBleHBvcnRzID09PSBcIm9iamVjdFwiKSB7XG5cdFx0Ly8gQ29tbW9uSlNcblx0XHRtb2R1bGUuZXhwb3J0cyA9IGV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoXCIuL2NvcmVcIikpO1xuXHR9XG5cdGVsc2UgaWYgKHR5cGVvZiBkZWZpbmUgPT09IFwiZnVuY3Rpb25cIiAmJiBkZWZpbmUuYW1kKSB7XG5cdFx0Ly8gQU1EXG5cdFx0ZGVmaW5lKFtcIi4vY29yZVwiXSwgZmFjdG9yeSk7XG5cdH1cblx0ZWxzZSB7XG5cdFx0Ly8gR2xvYmFsIChicm93c2VyKVxuXHRcdGZhY3Rvcnkocm9vdC5DcnlwdG9KUyk7XG5cdH1cbn0odGhpcywgZnVuY3Rpb24gKENyeXB0b0pTKSB7XG5cblx0KGZ1bmN0aW9uIChNYXRoKSB7XG5cdCAgICAvLyBTaG9ydGN1dHNcblx0ICAgIHZhciBDID0gQ3J5cHRvSlM7XG5cdCAgICB2YXIgQ19saWIgPSBDLmxpYjtcblx0ICAgIHZhciBXb3JkQXJyYXkgPSBDX2xpYi5Xb3JkQXJyYXk7XG5cdCAgICB2YXIgSGFzaGVyID0gQ19saWIuSGFzaGVyO1xuXHQgICAgdmFyIENfYWxnbyA9IEMuYWxnbztcblxuXHQgICAgLy8gQ29uc3RhbnRzIHRhYmxlXG5cdCAgICB2YXIgVCA9IFtdO1xuXG5cdCAgICAvLyBDb21wdXRlIGNvbnN0YW50c1xuXHQgICAgKGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDY0OyBpKyspIHtcblx0ICAgICAgICAgICAgVFtpXSA9IChNYXRoLmFicyhNYXRoLnNpbihpICsgMSkpICogMHgxMDAwMDAwMDApIHwgMDtcblx0ICAgICAgICB9XG5cdCAgICB9KCkpO1xuXG5cdCAgICAvKipcblx0ICAgICAqIE1ENSBoYXNoIGFsZ29yaXRobS5cblx0ICAgICAqL1xuXHQgICAgdmFyIE1ENSA9IENfYWxnby5NRDUgPSBIYXNoZXIuZXh0ZW5kKHtcblx0ICAgICAgICBfZG9SZXNldDogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICB0aGlzLl9oYXNoID0gbmV3IFdvcmRBcnJheS5pbml0KFtcblx0ICAgICAgICAgICAgICAgIDB4Njc0NTIzMDEsIDB4ZWZjZGFiODksXG5cdCAgICAgICAgICAgICAgICAweDk4YmFkY2ZlLCAweDEwMzI1NDc2XG5cdCAgICAgICAgICAgIF0pO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICBfZG9Qcm9jZXNzQmxvY2s6IGZ1bmN0aW9uIChNLCBvZmZzZXQpIHtcblx0ICAgICAgICAgICAgLy8gU3dhcCBlbmRpYW5cblx0ICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgaSsrKSB7XG5cdCAgICAgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgICAgIHZhciBvZmZzZXRfaSA9IG9mZnNldCArIGk7XG5cdCAgICAgICAgICAgICAgICB2YXIgTV9vZmZzZXRfaSA9IE1bb2Zmc2V0X2ldO1xuXG5cdCAgICAgICAgICAgICAgICBNW29mZnNldF9pXSA9IChcblx0ICAgICAgICAgICAgICAgICAgICAoKChNX29mZnNldF9pIDw8IDgpICB8IChNX29mZnNldF9pID4+PiAyNCkpICYgMHgwMGZmMDBmZikgfFxuXHQgICAgICAgICAgICAgICAgICAgICgoKE1fb2Zmc2V0X2kgPDwgMjQpIHwgKE1fb2Zmc2V0X2kgPj4+IDgpKSAgJiAweGZmMDBmZjAwKVxuXHQgICAgICAgICAgICAgICAgKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgSCA9IHRoaXMuX2hhc2gud29yZHM7XG5cblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzAgID0gTVtvZmZzZXQgKyAwXTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzEgID0gTVtvZmZzZXQgKyAxXTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzIgID0gTVtvZmZzZXQgKyAyXTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzMgID0gTVtvZmZzZXQgKyAzXTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzQgID0gTVtvZmZzZXQgKyA0XTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzUgID0gTVtvZmZzZXQgKyA1XTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzYgID0gTVtvZmZzZXQgKyA2XTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzcgID0gTVtvZmZzZXQgKyA3XTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzggID0gTVtvZmZzZXQgKyA4XTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzkgID0gTVtvZmZzZXQgKyA5XTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzEwID0gTVtvZmZzZXQgKyAxMF07XG5cdCAgICAgICAgICAgIHZhciBNX29mZnNldF8xMSA9IE1bb2Zmc2V0ICsgMTFdO1xuXHQgICAgICAgICAgICB2YXIgTV9vZmZzZXRfMTIgPSBNW29mZnNldCArIDEyXTtcblx0ICAgICAgICAgICAgdmFyIE1fb2Zmc2V0XzEzID0gTVtvZmZzZXQgKyAxM107XG5cdCAgICAgICAgICAgIHZhciBNX29mZnNldF8xNCA9IE1bb2Zmc2V0ICsgMTRdO1xuXHQgICAgICAgICAgICB2YXIgTV9vZmZzZXRfMTUgPSBNW29mZnNldCArIDE1XTtcblxuXHQgICAgICAgICAgICAvLyBXb3JraW5nIHZhcmlhbGJlc1xuXHQgICAgICAgICAgICB2YXIgYSA9IEhbMF07XG5cdCAgICAgICAgICAgIHZhciBiID0gSFsxXTtcblx0ICAgICAgICAgICAgdmFyIGMgPSBIWzJdO1xuXHQgICAgICAgICAgICB2YXIgZCA9IEhbM107XG5cblx0ICAgICAgICAgICAgLy8gQ29tcHV0YXRpb25cblx0ICAgICAgICAgICAgYSA9IEZGKGEsIGIsIGMsIGQsIE1fb2Zmc2V0XzAsICA3LCAgVFswXSk7XG5cdCAgICAgICAgICAgIGQgPSBGRihkLCBhLCBiLCBjLCBNX29mZnNldF8xLCAgMTIsIFRbMV0pO1xuXHQgICAgICAgICAgICBjID0gRkYoYywgZCwgYSwgYiwgTV9vZmZzZXRfMiwgIDE3LCBUWzJdKTtcblx0ICAgICAgICAgICAgYiA9IEZGKGIsIGMsIGQsIGEsIE1fb2Zmc2V0XzMsICAyMiwgVFszXSk7XG5cdCAgICAgICAgICAgIGEgPSBGRihhLCBiLCBjLCBkLCBNX29mZnNldF80LCAgNywgIFRbNF0pO1xuXHQgICAgICAgICAgICBkID0gRkYoZCwgYSwgYiwgYywgTV9vZmZzZXRfNSwgIDEyLCBUWzVdKTtcblx0ICAgICAgICAgICAgYyA9IEZGKGMsIGQsIGEsIGIsIE1fb2Zmc2V0XzYsICAxNywgVFs2XSk7XG5cdCAgICAgICAgICAgIGIgPSBGRihiLCBjLCBkLCBhLCBNX29mZnNldF83LCAgMjIsIFRbN10pO1xuXHQgICAgICAgICAgICBhID0gRkYoYSwgYiwgYywgZCwgTV9vZmZzZXRfOCwgIDcsICBUWzhdKTtcblx0ICAgICAgICAgICAgZCA9IEZGKGQsIGEsIGIsIGMsIE1fb2Zmc2V0XzksICAxMiwgVFs5XSk7XG5cdCAgICAgICAgICAgIGMgPSBGRihjLCBkLCBhLCBiLCBNX29mZnNldF8xMCwgMTcsIFRbMTBdKTtcblx0ICAgICAgICAgICAgYiA9IEZGKGIsIGMsIGQsIGEsIE1fb2Zmc2V0XzExLCAyMiwgVFsxMV0pO1xuXHQgICAgICAgICAgICBhID0gRkYoYSwgYiwgYywgZCwgTV9vZmZzZXRfMTIsIDcsICBUWzEyXSk7XG5cdCAgICAgICAgICAgIGQgPSBGRihkLCBhLCBiLCBjLCBNX29mZnNldF8xMywgMTIsIFRbMTNdKTtcblx0ICAgICAgICAgICAgYyA9IEZGKGMsIGQsIGEsIGIsIE1fb2Zmc2V0XzE0LCAxNywgVFsxNF0pO1xuXHQgICAgICAgICAgICBiID0gRkYoYiwgYywgZCwgYSwgTV9vZmZzZXRfMTUsIDIyLCBUWzE1XSk7XG5cblx0ICAgICAgICAgICAgYSA9IEdHKGEsIGIsIGMsIGQsIE1fb2Zmc2V0XzEsICA1LCAgVFsxNl0pO1xuXHQgICAgICAgICAgICBkID0gR0coZCwgYSwgYiwgYywgTV9vZmZzZXRfNiwgIDksICBUWzE3XSk7XG5cdCAgICAgICAgICAgIGMgPSBHRyhjLCBkLCBhLCBiLCBNX29mZnNldF8xMSwgMTQsIFRbMThdKTtcblx0ICAgICAgICAgICAgYiA9IEdHKGIsIGMsIGQsIGEsIE1fb2Zmc2V0XzAsICAyMCwgVFsxOV0pO1xuXHQgICAgICAgICAgICBhID0gR0coYSwgYiwgYywgZCwgTV9vZmZzZXRfNSwgIDUsICBUWzIwXSk7XG5cdCAgICAgICAgICAgIGQgPSBHRyhkLCBhLCBiLCBjLCBNX29mZnNldF8xMCwgOSwgIFRbMjFdKTtcblx0ICAgICAgICAgICAgYyA9IEdHKGMsIGQsIGEsIGIsIE1fb2Zmc2V0XzE1LCAxNCwgVFsyMl0pO1xuXHQgICAgICAgICAgICBiID0gR0coYiwgYywgZCwgYSwgTV9vZmZzZXRfNCwgIDIwLCBUWzIzXSk7XG5cdCAgICAgICAgICAgIGEgPSBHRyhhLCBiLCBjLCBkLCBNX29mZnNldF85LCAgNSwgIFRbMjRdKTtcblx0ICAgICAgICAgICAgZCA9IEdHKGQsIGEsIGIsIGMsIE1fb2Zmc2V0XzE0LCA5LCAgVFsyNV0pO1xuXHQgICAgICAgICAgICBjID0gR0coYywgZCwgYSwgYiwgTV9vZmZzZXRfMywgIDE0LCBUWzI2XSk7XG5cdCAgICAgICAgICAgIGIgPSBHRyhiLCBjLCBkLCBhLCBNX29mZnNldF84LCAgMjAsIFRbMjddKTtcblx0ICAgICAgICAgICAgYSA9IEdHKGEsIGIsIGMsIGQsIE1fb2Zmc2V0XzEzLCA1LCAgVFsyOF0pO1xuXHQgICAgICAgICAgICBkID0gR0coZCwgYSwgYiwgYywgTV9vZmZzZXRfMiwgIDksICBUWzI5XSk7XG5cdCAgICAgICAgICAgIGMgPSBHRyhjLCBkLCBhLCBiLCBNX29mZnNldF83LCAgMTQsIFRbMzBdKTtcblx0ICAgICAgICAgICAgYiA9IEdHKGIsIGMsIGQsIGEsIE1fb2Zmc2V0XzEyLCAyMCwgVFszMV0pO1xuXG5cdCAgICAgICAgICAgIGEgPSBISChhLCBiLCBjLCBkLCBNX29mZnNldF81LCAgNCwgIFRbMzJdKTtcblx0ICAgICAgICAgICAgZCA9IEhIKGQsIGEsIGIsIGMsIE1fb2Zmc2V0XzgsICAxMSwgVFszM10pO1xuXHQgICAgICAgICAgICBjID0gSEgoYywgZCwgYSwgYiwgTV9vZmZzZXRfMTEsIDE2LCBUWzM0XSk7XG5cdCAgICAgICAgICAgIGIgPSBISChiLCBjLCBkLCBhLCBNX29mZnNldF8xNCwgMjMsIFRbMzVdKTtcblx0ICAgICAgICAgICAgYSA9IEhIKGEsIGIsIGMsIGQsIE1fb2Zmc2V0XzEsICA0LCAgVFszNl0pO1xuXHQgICAgICAgICAgICBkID0gSEgoZCwgYSwgYiwgYywgTV9vZmZzZXRfNCwgIDExLCBUWzM3XSk7XG5cdCAgICAgICAgICAgIGMgPSBISChjLCBkLCBhLCBiLCBNX29mZnNldF83LCAgMTYsIFRbMzhdKTtcblx0ICAgICAgICAgICAgYiA9IEhIKGIsIGMsIGQsIGEsIE1fb2Zmc2V0XzEwLCAyMywgVFszOV0pO1xuXHQgICAgICAgICAgICBhID0gSEgoYSwgYiwgYywgZCwgTV9vZmZzZXRfMTMsIDQsICBUWzQwXSk7XG5cdCAgICAgICAgICAgIGQgPSBISChkLCBhLCBiLCBjLCBNX29mZnNldF8wLCAgMTEsIFRbNDFdKTtcblx0ICAgICAgICAgICAgYyA9IEhIKGMsIGQsIGEsIGIsIE1fb2Zmc2V0XzMsICAxNiwgVFs0Ml0pO1xuXHQgICAgICAgICAgICBiID0gSEgoYiwgYywgZCwgYSwgTV9vZmZzZXRfNiwgIDIzLCBUWzQzXSk7XG5cdCAgICAgICAgICAgIGEgPSBISChhLCBiLCBjLCBkLCBNX29mZnNldF85LCAgNCwgIFRbNDRdKTtcblx0ICAgICAgICAgICAgZCA9IEhIKGQsIGEsIGIsIGMsIE1fb2Zmc2V0XzEyLCAxMSwgVFs0NV0pO1xuXHQgICAgICAgICAgICBjID0gSEgoYywgZCwgYSwgYiwgTV9vZmZzZXRfMTUsIDE2LCBUWzQ2XSk7XG5cdCAgICAgICAgICAgIGIgPSBISChiLCBjLCBkLCBhLCBNX29mZnNldF8yLCAgMjMsIFRbNDddKTtcblxuXHQgICAgICAgICAgICBhID0gSUkoYSwgYiwgYywgZCwgTV9vZmZzZXRfMCwgIDYsICBUWzQ4XSk7XG5cdCAgICAgICAgICAgIGQgPSBJSShkLCBhLCBiLCBjLCBNX29mZnNldF83LCAgMTAsIFRbNDldKTtcblx0ICAgICAgICAgICAgYyA9IElJKGMsIGQsIGEsIGIsIE1fb2Zmc2V0XzE0LCAxNSwgVFs1MF0pO1xuXHQgICAgICAgICAgICBiID0gSUkoYiwgYywgZCwgYSwgTV9vZmZzZXRfNSwgIDIxLCBUWzUxXSk7XG5cdCAgICAgICAgICAgIGEgPSBJSShhLCBiLCBjLCBkLCBNX29mZnNldF8xMiwgNiwgIFRbNTJdKTtcblx0ICAgICAgICAgICAgZCA9IElJKGQsIGEsIGIsIGMsIE1fb2Zmc2V0XzMsICAxMCwgVFs1M10pO1xuXHQgICAgICAgICAgICBjID0gSUkoYywgZCwgYSwgYiwgTV9vZmZzZXRfMTAsIDE1LCBUWzU0XSk7XG5cdCAgICAgICAgICAgIGIgPSBJSShiLCBjLCBkLCBhLCBNX29mZnNldF8xLCAgMjEsIFRbNTVdKTtcblx0ICAgICAgICAgICAgYSA9IElJKGEsIGIsIGMsIGQsIE1fb2Zmc2V0XzgsICA2LCAgVFs1Nl0pO1xuXHQgICAgICAgICAgICBkID0gSUkoZCwgYSwgYiwgYywgTV9vZmZzZXRfMTUsIDEwLCBUWzU3XSk7XG5cdCAgICAgICAgICAgIGMgPSBJSShjLCBkLCBhLCBiLCBNX29mZnNldF82LCAgMTUsIFRbNThdKTtcblx0ICAgICAgICAgICAgYiA9IElJKGIsIGMsIGQsIGEsIE1fb2Zmc2V0XzEzLCAyMSwgVFs1OV0pO1xuXHQgICAgICAgICAgICBhID0gSUkoYSwgYiwgYywgZCwgTV9vZmZzZXRfNCwgIDYsICBUWzYwXSk7XG5cdCAgICAgICAgICAgIGQgPSBJSShkLCBhLCBiLCBjLCBNX29mZnNldF8xMSwgMTAsIFRbNjFdKTtcblx0ICAgICAgICAgICAgYyA9IElJKGMsIGQsIGEsIGIsIE1fb2Zmc2V0XzIsICAxNSwgVFs2Ml0pO1xuXHQgICAgICAgICAgICBiID0gSUkoYiwgYywgZCwgYSwgTV9vZmZzZXRfOSwgIDIxLCBUWzYzXSk7XG5cblx0ICAgICAgICAgICAgLy8gSW50ZXJtZWRpYXRlIGhhc2ggdmFsdWVcblx0ICAgICAgICAgICAgSFswXSA9IChIWzBdICsgYSkgfCAwO1xuXHQgICAgICAgICAgICBIWzFdID0gKEhbMV0gKyBiKSB8IDA7XG5cdCAgICAgICAgICAgIEhbMl0gPSAoSFsyXSArIGMpIHwgMDtcblx0ICAgICAgICAgICAgSFszXSA9IChIWzNdICsgZCkgfCAwO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICBfZG9GaW5hbGl6ZTogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICAvLyBTaG9ydGN1dHNcblx0ICAgICAgICAgICAgdmFyIGRhdGEgPSB0aGlzLl9kYXRhO1xuXHQgICAgICAgICAgICB2YXIgZGF0YVdvcmRzID0gZGF0YS53b3JkcztcblxuXHQgICAgICAgICAgICB2YXIgbkJpdHNUb3RhbCA9IHRoaXMuX25EYXRhQnl0ZXMgKiA4O1xuXHQgICAgICAgICAgICB2YXIgbkJpdHNMZWZ0ID0gZGF0YS5zaWdCeXRlcyAqIDg7XG5cblx0ICAgICAgICAgICAgLy8gQWRkIHBhZGRpbmdcblx0ICAgICAgICAgICAgZGF0YVdvcmRzW25CaXRzTGVmdCA+Pj4gNV0gfD0gMHg4MCA8PCAoMjQgLSBuQml0c0xlZnQgJSAzMik7XG5cblx0ICAgICAgICAgICAgdmFyIG5CaXRzVG90YWxIID0gTWF0aC5mbG9vcihuQml0c1RvdGFsIC8gMHgxMDAwMDAwMDApO1xuXHQgICAgICAgICAgICB2YXIgbkJpdHNUb3RhbEwgPSBuQml0c1RvdGFsO1xuXHQgICAgICAgICAgICBkYXRhV29yZHNbKCgobkJpdHNMZWZ0ICsgNjQpID4+PiA5KSA8PCA0KSArIDE1XSA9IChcblx0ICAgICAgICAgICAgICAgICgoKG5CaXRzVG90YWxIIDw8IDgpICB8IChuQml0c1RvdGFsSCA+Pj4gMjQpKSAmIDB4MDBmZjAwZmYpIHxcblx0ICAgICAgICAgICAgICAgICgoKG5CaXRzVG90YWxIIDw8IDI0KSB8IChuQml0c1RvdGFsSCA+Pj4gOCkpICAmIDB4ZmYwMGZmMDApXG5cdCAgICAgICAgICAgICk7XG5cdCAgICAgICAgICAgIGRhdGFXb3Jkc1soKChuQml0c0xlZnQgKyA2NCkgPj4+IDkpIDw8IDQpICsgMTRdID0gKFxuXHQgICAgICAgICAgICAgICAgKCgobkJpdHNUb3RhbEwgPDwgOCkgIHwgKG5CaXRzVG90YWxMID4+PiAyNCkpICYgMHgwMGZmMDBmZikgfFxuXHQgICAgICAgICAgICAgICAgKCgobkJpdHNUb3RhbEwgPDwgMjQpIHwgKG5CaXRzVG90YWxMID4+PiA4KSkgICYgMHhmZjAwZmYwMClcblx0ICAgICAgICAgICAgKTtcblxuXHQgICAgICAgICAgICBkYXRhLnNpZ0J5dGVzID0gKGRhdGFXb3Jkcy5sZW5ndGggKyAxKSAqIDQ7XG5cblx0ICAgICAgICAgICAgLy8gSGFzaCBmaW5hbCBibG9ja3Ncblx0ICAgICAgICAgICAgdGhpcy5fcHJvY2VzcygpO1xuXG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgaGFzaCA9IHRoaXMuX2hhc2g7XG5cdCAgICAgICAgICAgIHZhciBIID0gaGFzaC53b3JkcztcblxuXHQgICAgICAgICAgICAvLyBTd2FwIGVuZGlhblxuXHQgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDQ7IGkrKykge1xuXHQgICAgICAgICAgICAgICAgLy8gU2hvcnRjdXRcblx0ICAgICAgICAgICAgICAgIHZhciBIX2kgPSBIW2ldO1xuXG5cdCAgICAgICAgICAgICAgICBIW2ldID0gKCgoSF9pIDw8IDgpICB8IChIX2kgPj4+IDI0KSkgJiAweDAwZmYwMGZmKSB8XG5cdCAgICAgICAgICAgICAgICAgICAgICAgKCgoSF9pIDw8IDI0KSB8IChIX2kgPj4+IDgpKSAgJiAweGZmMDBmZjAwKTtcblx0ICAgICAgICAgICAgfVxuXG5cdCAgICAgICAgICAgIC8vIFJldHVybiBmaW5hbCBjb21wdXRlZCBoYXNoXG5cdCAgICAgICAgICAgIHJldHVybiBoYXNoO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICBjbG9uZTogZnVuY3Rpb24gKCkge1xuXHQgICAgICAgICAgICB2YXIgY2xvbmUgPSBIYXNoZXIuY2xvbmUuY2FsbCh0aGlzKTtcblx0ICAgICAgICAgICAgY2xvbmUuX2hhc2ggPSB0aGlzLl9oYXNoLmNsb25lKCk7XG5cblx0ICAgICAgICAgICAgcmV0dXJuIGNsb25lO1xuXHQgICAgICAgIH1cblx0ICAgIH0pO1xuXG5cdCAgICBmdW5jdGlvbiBGRihhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG5cdCAgICAgICAgdmFyIG4gPSBhICsgKChiICYgYykgfCAofmIgJiBkKSkgKyB4ICsgdDtcblx0ICAgICAgICByZXR1cm4gKChuIDw8IHMpIHwgKG4gPj4+ICgzMiAtIHMpKSkgKyBiO1xuXHQgICAgfVxuXG5cdCAgICBmdW5jdGlvbiBHRyhhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG5cdCAgICAgICAgdmFyIG4gPSBhICsgKChiICYgZCkgfCAoYyAmIH5kKSkgKyB4ICsgdDtcblx0ICAgICAgICByZXR1cm4gKChuIDw8IHMpIHwgKG4gPj4+ICgzMiAtIHMpKSkgKyBiO1xuXHQgICAgfVxuXG5cdCAgICBmdW5jdGlvbiBISChhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG5cdCAgICAgICAgdmFyIG4gPSBhICsgKGIgXiBjIF4gZCkgKyB4ICsgdDtcblx0ICAgICAgICByZXR1cm4gKChuIDw8IHMpIHwgKG4gPj4+ICgzMiAtIHMpKSkgKyBiO1xuXHQgICAgfVxuXG5cdCAgICBmdW5jdGlvbiBJSShhLCBiLCBjLCBkLCB4LCBzLCB0KSB7XG5cdCAgICAgICAgdmFyIG4gPSBhICsgKGMgXiAoYiB8IH5kKSkgKyB4ICsgdDtcblx0ICAgICAgICByZXR1cm4gKChuIDw8IHMpIHwgKG4gPj4+ICgzMiAtIHMpKSkgKyBiO1xuXHQgICAgfVxuXG5cdCAgICAvKipcblx0ICAgICAqIFNob3J0Y3V0IGZ1bmN0aW9uIHRvIHRoZSBoYXNoZXIncyBvYmplY3QgaW50ZXJmYWNlLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30gbWVzc2FnZSBUaGUgbWVzc2FnZSB0byBoYXNoLlxuXHQgICAgICpcblx0ICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIGhhc2guXG5cdCAgICAgKlxuXHQgICAgICogQHN0YXRpY1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogICAgIHZhciBoYXNoID0gQ3J5cHRvSlMuTUQ1KCdtZXNzYWdlJyk7XG5cdCAgICAgKiAgICAgdmFyIGhhc2ggPSBDcnlwdG9KUy5NRDUod29yZEFycmF5KTtcblx0ICAgICAqL1xuXHQgICAgQy5NRDUgPSBIYXNoZXIuX2NyZWF0ZUhlbHBlcihNRDUpO1xuXG5cdCAgICAvKipcblx0ICAgICAqIFNob3J0Y3V0IGZ1bmN0aW9uIHRvIHRoZSBITUFDJ3Mgb2JqZWN0IGludGVyZmFjZS5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gaGFzaC5cblx0ICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30ga2V5IFRoZSBzZWNyZXQga2V5LlxuXHQgICAgICpcblx0ICAgICAqIEByZXR1cm4ge1dvcmRBcnJheX0gVGhlIEhNQUMuXG5cdCAgICAgKlxuXHQgICAgICogQHN0YXRpY1xuXHQgICAgICpcblx0ICAgICAqIEBleGFtcGxlXG5cdCAgICAgKlxuXHQgICAgICogICAgIHZhciBobWFjID0gQ3J5cHRvSlMuSG1hY01ENShtZXNzYWdlLCBrZXkpO1xuXHQgICAgICovXG5cdCAgICBDLkhtYWNNRDUgPSBIYXNoZXIuX2NyZWF0ZUhtYWNIZWxwZXIoTUQ1KTtcblx0fShNYXRoKSk7XG5cblxuXHRyZXR1cm4gQ3J5cHRvSlMuTUQ1O1xuXG59KSk7IiwiOyhmdW5jdGlvbiAocm9vdCwgZmFjdG9yeSkge1xuXHRpZiAodHlwZW9mIGV4cG9ydHMgPT09IFwib2JqZWN0XCIpIHtcblx0XHQvLyBDb21tb25KU1xuXHRcdG1vZHVsZS5leHBvcnRzID0gZXhwb3J0cyA9IGZhY3RvcnkocmVxdWlyZShcIi4vY29yZVwiKSk7XG5cdH1cblx0ZWxzZSBpZiAodHlwZW9mIGRlZmluZSA9PT0gXCJmdW5jdGlvblwiICYmIGRlZmluZS5hbWQpIHtcblx0XHQvLyBBTURcblx0XHRkZWZpbmUoW1wiLi9jb3JlXCJdLCBmYWN0b3J5KTtcblx0fVxuXHRlbHNlIHtcblx0XHQvLyBHbG9iYWwgKGJyb3dzZXIpXG5cdFx0ZmFjdG9yeShyb290LkNyeXB0b0pTKTtcblx0fVxufSh0aGlzLCBmdW5jdGlvbiAoQ3J5cHRvSlMpIHtcblxuXHQoZnVuY3Rpb24gKCkge1xuXHQgICAgLy8gU2hvcnRjdXRzXG5cdCAgICB2YXIgQyA9IENyeXB0b0pTO1xuXHQgICAgdmFyIENfbGliID0gQy5saWI7XG5cdCAgICB2YXIgV29yZEFycmF5ID0gQ19saWIuV29yZEFycmF5O1xuXHQgICAgdmFyIEhhc2hlciA9IENfbGliLkhhc2hlcjtcblx0ICAgIHZhciBDX2FsZ28gPSBDLmFsZ287XG5cblx0ICAgIC8vIFJldXNhYmxlIG9iamVjdFxuXHQgICAgdmFyIFcgPSBbXTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTSEEtMSBoYXNoIGFsZ29yaXRobS5cblx0ICAgICAqL1xuXHQgICAgdmFyIFNIQTEgPSBDX2FsZ28uU0hBMSA9IEhhc2hlci5leHRlbmQoe1xuXHQgICAgICAgIF9kb1Jlc2V0OiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIHRoaXMuX2hhc2ggPSBuZXcgV29yZEFycmF5LmluaXQoW1xuXHQgICAgICAgICAgICAgICAgMHg2NzQ1MjMwMSwgMHhlZmNkYWI4OSxcblx0ICAgICAgICAgICAgICAgIDB4OThiYWRjZmUsIDB4MTAzMjU0NzYsXG5cdCAgICAgICAgICAgICAgICAweGMzZDJlMWYwXG5cdCAgICAgICAgICAgIF0pO1xuXHQgICAgICAgIH0sXG5cblx0ICAgICAgICBfZG9Qcm9jZXNzQmxvY2s6IGZ1bmN0aW9uIChNLCBvZmZzZXQpIHtcblx0ICAgICAgICAgICAgLy8gU2hvcnRjdXRcblx0ICAgICAgICAgICAgdmFyIEggPSB0aGlzLl9oYXNoLndvcmRzO1xuXG5cdCAgICAgICAgICAgIC8vIFdvcmtpbmcgdmFyaWFibGVzXG5cdCAgICAgICAgICAgIHZhciBhID0gSFswXTtcblx0ICAgICAgICAgICAgdmFyIGIgPSBIWzFdO1xuXHQgICAgICAgICAgICB2YXIgYyA9IEhbMl07XG5cdCAgICAgICAgICAgIHZhciBkID0gSFszXTtcblx0ICAgICAgICAgICAgdmFyIGUgPSBIWzRdO1xuXG5cdCAgICAgICAgICAgIC8vIENvbXB1dGF0aW9uXG5cdCAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgODA7IGkrKykge1xuXHQgICAgICAgICAgICAgICAgaWYgKGkgPCAxNikge1xuXHQgICAgICAgICAgICAgICAgICAgIFdbaV0gPSBNW29mZnNldCArIGldIHwgMDtcblx0ICAgICAgICAgICAgICAgIH0gZWxzZSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdmFyIG4gPSBXW2kgLSAzXSBeIFdbaSAtIDhdIF4gV1tpIC0gMTRdIF4gV1tpIC0gMTZdO1xuXHQgICAgICAgICAgICAgICAgICAgIFdbaV0gPSAobiA8PCAxKSB8IChuID4+PiAzMSk7XG5cdCAgICAgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgICAgIHZhciB0ID0gKChhIDw8IDUpIHwgKGEgPj4+IDI3KSkgKyBlICsgV1tpXTtcblx0ICAgICAgICAgICAgICAgIGlmIChpIDwgMjApIHtcblx0ICAgICAgICAgICAgICAgICAgICB0ICs9ICgoYiAmIGMpIHwgKH5iICYgZCkpICsgMHg1YTgyNzk5OTtcblx0ICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaSA8IDQwKSB7XG5cdCAgICAgICAgICAgICAgICAgICAgdCArPSAoYiBeIGMgXiBkKSArIDB4NmVkOWViYTE7XG5cdCAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKGkgPCA2MCkge1xuXHQgICAgICAgICAgICAgICAgICAgIHQgKz0gKChiICYgYykgfCAoYiAmIGQpIHwgKGMgJiBkKSkgLSAweDcwZTQ0MzI0O1xuXHQgICAgICAgICAgICAgICAgfSBlbHNlIC8qIGlmIChpIDwgODApICovIHtcblx0ICAgICAgICAgICAgICAgICAgICB0ICs9IChiIF4gYyBeIGQpIC0gMHgzNTlkM2UyYTtcblx0ICAgICAgICAgICAgICAgIH1cblxuXHQgICAgICAgICAgICAgICAgZSA9IGQ7XG5cdCAgICAgICAgICAgICAgICBkID0gYztcblx0ICAgICAgICAgICAgICAgIGMgPSAoYiA8PCAzMCkgfCAoYiA+Pj4gMik7XG5cdCAgICAgICAgICAgICAgICBiID0gYTtcblx0ICAgICAgICAgICAgICAgIGEgPSB0O1xuXHQgICAgICAgICAgICB9XG5cblx0ICAgICAgICAgICAgLy8gSW50ZXJtZWRpYXRlIGhhc2ggdmFsdWVcblx0ICAgICAgICAgICAgSFswXSA9IChIWzBdICsgYSkgfCAwO1xuXHQgICAgICAgICAgICBIWzFdID0gKEhbMV0gKyBiKSB8IDA7XG5cdCAgICAgICAgICAgIEhbMl0gPSAoSFsyXSArIGMpIHwgMDtcblx0ICAgICAgICAgICAgSFszXSA9IChIWzNdICsgZCkgfCAwO1xuXHQgICAgICAgICAgICBIWzRdID0gKEhbNF0gKyBlKSB8IDA7XG5cdCAgICAgICAgfSxcblxuXHQgICAgICAgIF9kb0ZpbmFsaXplOiBmdW5jdGlvbiAoKSB7XG5cdCAgICAgICAgICAgIC8vIFNob3J0Y3V0c1xuXHQgICAgICAgICAgICB2YXIgZGF0YSA9IHRoaXMuX2RhdGE7XG5cdCAgICAgICAgICAgIHZhciBkYXRhV29yZHMgPSBkYXRhLndvcmRzO1xuXG5cdCAgICAgICAgICAgIHZhciBuQml0c1RvdGFsID0gdGhpcy5fbkRhdGFCeXRlcyAqIDg7XG5cdCAgICAgICAgICAgIHZhciBuQml0c0xlZnQgPSBkYXRhLnNpZ0J5dGVzICogODtcblxuXHQgICAgICAgICAgICAvLyBBZGQgcGFkZGluZ1xuXHQgICAgICAgICAgICBkYXRhV29yZHNbbkJpdHNMZWZ0ID4+PiA1XSB8PSAweDgwIDw8ICgyNCAtIG5CaXRzTGVmdCAlIDMyKTtcblx0ICAgICAgICAgICAgZGF0YVdvcmRzWygoKG5CaXRzTGVmdCArIDY0KSA+Pj4gOSkgPDwgNCkgKyAxNF0gPSBNYXRoLmZsb29yKG5CaXRzVG90YWwgLyAweDEwMDAwMDAwMCk7XG5cdCAgICAgICAgICAgIGRhdGFXb3Jkc1soKChuQml0c0xlZnQgKyA2NCkgPj4+IDkpIDw8IDQpICsgMTVdID0gbkJpdHNUb3RhbDtcblx0ICAgICAgICAgICAgZGF0YS5zaWdCeXRlcyA9IGRhdGFXb3Jkcy5sZW5ndGggKiA0O1xuXG5cdCAgICAgICAgICAgIC8vIEhhc2ggZmluYWwgYmxvY2tzXG5cdCAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3MoKTtcblxuXHQgICAgICAgICAgICAvLyBSZXR1cm4gZmluYWwgY29tcHV0ZWQgaGFzaFxuXHQgICAgICAgICAgICByZXR1cm4gdGhpcy5faGFzaDtcblx0ICAgICAgICB9LFxuXG5cdCAgICAgICAgY2xvbmU6IGZ1bmN0aW9uICgpIHtcblx0ICAgICAgICAgICAgdmFyIGNsb25lID0gSGFzaGVyLmNsb25lLmNhbGwodGhpcyk7XG5cdCAgICAgICAgICAgIGNsb25lLl9oYXNoID0gdGhpcy5faGFzaC5jbG9uZSgpO1xuXG5cdCAgICAgICAgICAgIHJldHVybiBjbG9uZTtcblx0ICAgICAgICB9XG5cdCAgICB9KTtcblxuXHQgICAgLyoqXG5cdCAgICAgKiBTaG9ydGN1dCBmdW5jdGlvbiB0byB0aGUgaGFzaGVyJ3Mgb2JqZWN0IGludGVyZmFjZS5cblx0ICAgICAqXG5cdCAgICAgKiBAcGFyYW0ge1dvcmRBcnJheXxzdHJpbmd9IG1lc3NhZ2UgVGhlIG1lc3NhZ2UgdG8gaGFzaC5cblx0ICAgICAqXG5cdCAgICAgKiBAcmV0dXJuIHtXb3JkQXJyYXl9IFRoZSBoYXNoLlxuXHQgICAgICpcblx0ICAgICAqIEBzdGF0aWNcblx0ICAgICAqXG5cdCAgICAgKiBAZXhhbXBsZVxuXHQgICAgICpcblx0ICAgICAqICAgICB2YXIgaGFzaCA9IENyeXB0b0pTLlNIQTEoJ21lc3NhZ2UnKTtcblx0ICAgICAqICAgICB2YXIgaGFzaCA9IENyeXB0b0pTLlNIQTEod29yZEFycmF5KTtcblx0ICAgICAqL1xuXHQgICAgQy5TSEExID0gSGFzaGVyLl9jcmVhdGVIZWxwZXIoU0hBMSk7XG5cblx0ICAgIC8qKlxuXHQgICAgICogU2hvcnRjdXQgZnVuY3Rpb24gdG8gdGhlIEhNQUMncyBvYmplY3QgaW50ZXJmYWNlLlxuXHQgICAgICpcblx0ICAgICAqIEBwYXJhbSB7V29yZEFycmF5fHN0cmluZ30gbWVzc2FnZSBUaGUgbWVzc2FnZSB0byBoYXNoLlxuXHQgICAgICogQHBhcmFtIHtXb3JkQXJyYXl8c3RyaW5nfSBrZXkgVGhlIHNlY3JldCBrZXkuXG5cdCAgICAgKlxuXHQgICAgICogQHJldHVybiB7V29yZEFycmF5fSBUaGUgSE1BQy5cblx0ICAgICAqXG5cdCAgICAgKiBAc3RhdGljXG5cdCAgICAgKlxuXHQgICAgICogQGV4YW1wbGVcblx0ICAgICAqXG5cdCAgICAgKiAgICAgdmFyIGhtYWMgPSBDcnlwdG9KUy5IbWFjU0hBMShtZXNzYWdlLCBrZXkpO1xuXHQgICAgICovXG5cdCAgICBDLkhtYWNTSEExID0gSGFzaGVyLl9jcmVhdGVIbWFjSGVscGVyKFNIQTEpO1xuXHR9KCkpO1xuXG5cblx0cmV0dXJuIENyeXB0b0pTLlNIQTE7XG5cbn0pKTsiLCJ2YXIgcFNsaWNlID0gQXJyYXkucHJvdG90eXBlLnNsaWNlO1xudmFyIG9iamVjdEtleXMgPSByZXF1aXJlKCcuL2xpYi9rZXlzLmpzJyk7XG52YXIgaXNBcmd1bWVudHMgPSByZXF1aXJlKCcuL2xpYi9pc19hcmd1bWVudHMuanMnKTtcblxudmFyIGRlZXBFcXVhbCA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gKGFjdHVhbCwgZXhwZWN0ZWQsIG9wdHMpIHtcbiAgaWYgKCFvcHRzKSBvcHRzID0ge307XG4gIC8vIDcuMS4gQWxsIGlkZW50aWNhbCB2YWx1ZXMgYXJlIGVxdWl2YWxlbnQsIGFzIGRldGVybWluZWQgYnkgPT09LlxuICBpZiAoYWN0dWFsID09PSBleHBlY3RlZCkge1xuICAgIHJldHVybiB0cnVlO1xuXG4gIH0gZWxzZSBpZiAoYWN0dWFsIGluc3RhbmNlb2YgRGF0ZSAmJiBleHBlY3RlZCBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICByZXR1cm4gYWN0dWFsLmdldFRpbWUoKSA9PT0gZXhwZWN0ZWQuZ2V0VGltZSgpO1xuXG4gIC8vIDcuMy4gT3RoZXIgcGFpcnMgdGhhdCBkbyBub3QgYm90aCBwYXNzIHR5cGVvZiB2YWx1ZSA9PSAnb2JqZWN0JyxcbiAgLy8gZXF1aXZhbGVuY2UgaXMgZGV0ZXJtaW5lZCBieSA9PS5cbiAgfSBlbHNlIGlmICghYWN0dWFsIHx8ICFleHBlY3RlZCB8fCB0eXBlb2YgYWN0dWFsICE9ICdvYmplY3QnICYmIHR5cGVvZiBleHBlY3RlZCAhPSAnb2JqZWN0Jykge1xuICAgIHJldHVybiBvcHRzLnN0cmljdCA/IGFjdHVhbCA9PT0gZXhwZWN0ZWQgOiBhY3R1YWwgPT0gZXhwZWN0ZWQ7XG5cbiAgLy8gNy40LiBGb3IgYWxsIG90aGVyIE9iamVjdCBwYWlycywgaW5jbHVkaW5nIEFycmF5IG9iamVjdHMsIGVxdWl2YWxlbmNlIGlzXG4gIC8vIGRldGVybWluZWQgYnkgaGF2aW5nIHRoZSBzYW1lIG51bWJlciBvZiBvd25lZCBwcm9wZXJ0aWVzIChhcyB2ZXJpZmllZFxuICAvLyB3aXRoIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbCksIHRoZSBzYW1lIHNldCBvZiBrZXlzXG4gIC8vIChhbHRob3VnaCBub3QgbmVjZXNzYXJpbHkgdGhlIHNhbWUgb3JkZXIpLCBlcXVpdmFsZW50IHZhbHVlcyBmb3IgZXZlcnlcbiAgLy8gY29ycmVzcG9uZGluZyBrZXksIGFuZCBhbiBpZGVudGljYWwgJ3Byb3RvdHlwZScgcHJvcGVydHkuIE5vdGU6IHRoaXNcbiAgLy8gYWNjb3VudHMgZm9yIGJvdGggbmFtZWQgYW5kIGluZGV4ZWQgcHJvcGVydGllcyBvbiBBcnJheXMuXG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIG9iakVxdWl2KGFjdHVhbCwgZXhwZWN0ZWQsIG9wdHMpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkT3JOdWxsKHZhbHVlKSB7XG4gIHJldHVybiB2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBpc0J1ZmZlciAoeCkge1xuICBpZiAoIXggfHwgdHlwZW9mIHggIT09ICdvYmplY3QnIHx8IHR5cGVvZiB4Lmxlbmd0aCAhPT0gJ251bWJlcicpIHJldHVybiBmYWxzZTtcbiAgaWYgKHR5cGVvZiB4LmNvcHkgIT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIHguc2xpY2UgIT09ICdmdW5jdGlvbicpIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgaWYgKHgubGVuZ3RoID4gMCAmJiB0eXBlb2YgeFswXSAhPT0gJ251bWJlcicpIHJldHVybiBmYWxzZTtcbiAgcmV0dXJuIHRydWU7XG59XG5cbmZ1bmN0aW9uIG9iakVxdWl2KGEsIGIsIG9wdHMpIHtcbiAgdmFyIGksIGtleTtcbiAgaWYgKGlzVW5kZWZpbmVkT3JOdWxsKGEpIHx8IGlzVW5kZWZpbmVkT3JOdWxsKGIpKVxuICAgIHJldHVybiBmYWxzZTtcbiAgLy8gYW4gaWRlbnRpY2FsICdwcm90b3R5cGUnIHByb3BlcnR5LlxuICBpZiAoYS5wcm90b3R5cGUgIT09IGIucHJvdG90eXBlKSByZXR1cm4gZmFsc2U7XG4gIC8vfn5+SSd2ZSBtYW5hZ2VkIHRvIGJyZWFrIE9iamVjdC5rZXlzIHRocm91Z2ggc2NyZXd5IGFyZ3VtZW50cyBwYXNzaW5nLlxuICAvLyAgIENvbnZlcnRpbmcgdG8gYXJyYXkgc29sdmVzIHRoZSBwcm9ibGVtLlxuICBpZiAoaXNBcmd1bWVudHMoYSkpIHtcbiAgICBpZiAoIWlzQXJndW1lbnRzKGIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGEgPSBwU2xpY2UuY2FsbChhKTtcbiAgICBiID0gcFNsaWNlLmNhbGwoYik7XG4gICAgcmV0dXJuIGRlZXBFcXVhbChhLCBiLCBvcHRzKTtcbiAgfVxuICBpZiAoaXNCdWZmZXIoYSkpIHtcbiAgICBpZiAoIWlzQnVmZmVyKGIpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIGlmIChhLmxlbmd0aCAhPT0gYi5sZW5ndGgpIHJldHVybiBmYWxzZTtcbiAgICBmb3IgKGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKGFbaV0gIT09IGJbaV0pIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cbiAgdHJ5IHtcbiAgICB2YXIga2EgPSBvYmplY3RLZXlzKGEpLFxuICAgICAgICBrYiA9IG9iamVjdEtleXMoYik7XG4gIH0gY2F0Y2ggKGUpIHsvL2hhcHBlbnMgd2hlbiBvbmUgaXMgYSBzdHJpbmcgbGl0ZXJhbCBhbmQgdGhlIG90aGVyIGlzbid0XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG4gIC8vIGhhdmluZyB0aGUgc2FtZSBudW1iZXIgb2Ygb3duZWQgcHJvcGVydGllcyAoa2V5cyBpbmNvcnBvcmF0ZXNcbiAgLy8gaGFzT3duUHJvcGVydHkpXG4gIGlmIChrYS5sZW5ndGggIT0ga2IubGVuZ3RoKVxuICAgIHJldHVybiBmYWxzZTtcbiAgLy90aGUgc2FtZSBzZXQgb2Yga2V5cyAoYWx0aG91Z2ggbm90IG5lY2Vzc2FyaWx5IHRoZSBzYW1lIG9yZGVyKSxcbiAga2Euc29ydCgpO1xuICBrYi5zb3J0KCk7XG4gIC8vfn5+Y2hlYXAga2V5IHRlc3RcbiAgZm9yIChpID0ga2EubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBpZiAoa2FbaV0gIT0ga2JbaV0pXG4gICAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgLy9lcXVpdmFsZW50IHZhbHVlcyBmb3IgZXZlcnkgY29ycmVzcG9uZGluZyBrZXksIGFuZFxuICAvL35+fnBvc3NpYmx5IGV4cGVuc2l2ZSBkZWVwIHRlc3RcbiAgZm9yIChpID0ga2EubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICBrZXkgPSBrYVtpXTtcbiAgICBpZiAoIWRlZXBFcXVhbChhW2tleV0sIGJba2V5XSwgb3B0cykpIHJldHVybiBmYWxzZTtcbiAgfVxuICByZXR1cm4gdHlwZW9mIGEgPT09IHR5cGVvZiBiO1xufVxuIiwidmFyIHN1cHBvcnRzQXJndW1lbnRzQ2xhc3MgPSAoZnVuY3Rpb24oKXtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhcmd1bWVudHMpXG59KSgpID09ICdbb2JqZWN0IEFyZ3VtZW50c10nO1xuXG5leHBvcnRzID0gbW9kdWxlLmV4cG9ydHMgPSBzdXBwb3J0c0FyZ3VtZW50c0NsYXNzID8gc3VwcG9ydGVkIDogdW5zdXBwb3J0ZWQ7XG5cbmV4cG9ydHMuc3VwcG9ydGVkID0gc3VwcG9ydGVkO1xuZnVuY3Rpb24gc3VwcG9ydGVkKG9iamVjdCkge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iamVjdCkgPT0gJ1tvYmplY3QgQXJndW1lbnRzXSc7XG59O1xuXG5leHBvcnRzLnVuc3VwcG9ydGVkID0gdW5zdXBwb3J0ZWQ7XG5mdW5jdGlvbiB1bnN1cHBvcnRlZChvYmplY3Qpe1xuICByZXR1cm4gb2JqZWN0ICYmXG4gICAgdHlwZW9mIG9iamVjdCA9PSAnb2JqZWN0JyAmJlxuICAgIHR5cGVvZiBvYmplY3QubGVuZ3RoID09ICdudW1iZXInICYmXG4gICAgT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKG9iamVjdCwgJ2NhbGxlZScpICYmXG4gICAgIU9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChvYmplY3QsICdjYWxsZWUnKSB8fFxuICAgIGZhbHNlO1xufTtcbiIsImV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IHR5cGVvZiBPYmplY3Qua2V5cyA9PT0gJ2Z1bmN0aW9uJ1xuICA/IE9iamVjdC5rZXlzIDogc2hpbTtcblxuZXhwb3J0cy5zaGltID0gc2hpbTtcbmZ1bmN0aW9uIHNoaW0gKG9iaikge1xuICB2YXIga2V5cyA9IFtdO1xuICBmb3IgKHZhciBrZXkgaW4gb2JqKSBrZXlzLnB1c2goa2V5KTtcbiAgcmV0dXJuIGtleXM7XG59XG4iLCJ2YXIgYXNzZXJ0ID0gcmVxdWlyZSgnYXNzZXJ0JylcbnZhciBCaWdJbnRlZ2VyID0gcmVxdWlyZSgnYmlnaScpXG5cbnZhciBQb2ludCA9IHJlcXVpcmUoJy4vcG9pbnQnKVxuXG5mdW5jdGlvbiBDdXJ2ZSAocCwgYSwgYiwgR3gsIEd5LCBuLCBoKSB7XG4gIHRoaXMucCA9IHBcbiAgdGhpcy5hID0gYVxuICB0aGlzLmIgPSBiXG4gIHRoaXMuRyA9IFBvaW50LmZyb21BZmZpbmUodGhpcywgR3gsIEd5KVxuICB0aGlzLm4gPSBuXG4gIHRoaXMuaCA9IGhcblxuICB0aGlzLmluZmluaXR5ID0gbmV3IFBvaW50KHRoaXMsIG51bGwsIG51bGwsIEJpZ0ludGVnZXIuWkVSTylcblxuICAvLyByZXN1bHQgY2FjaGluZ1xuICB0aGlzLnBPdmVyRm91ciA9IHAuYWRkKEJpZ0ludGVnZXIuT05FKS5zaGlmdFJpZ2h0KDIpXG5cbiAgLy8gZGV0ZXJtaW5lIHNpemUgb2YgcCBpbiBieXRlc1xuICB0aGlzLnBMZW5ndGggPSBNYXRoLmZsb29yKCh0aGlzLnAuYml0TGVuZ3RoKCkgKyA3KSAvIDgpXG59XG5cbkN1cnZlLnByb3RvdHlwZS5wb2ludEZyb21YID0gZnVuY3Rpb24gKGlzT2RkLCB4KSB7XG4gIHZhciBhbHBoYSA9IHgucG93KDMpLmFkZCh0aGlzLmEubXVsdGlwbHkoeCkpLmFkZCh0aGlzLmIpLm1vZCh0aGlzLnApXG4gIHZhciBiZXRhID0gYWxwaGEubW9kUG93KHRoaXMucE92ZXJGb3VyLCB0aGlzLnApIC8vIFhYWDogbm90IGNvbXBhdGlibGUgd2l0aCBhbGwgY3VydmVzXG5cbiAgdmFyIHkgPSBiZXRhXG4gIGlmIChiZXRhLmlzRXZlbigpIF4gIWlzT2RkKSB7XG4gICAgeSA9IHRoaXMucC5zdWJ0cmFjdCh5KSAvLyAteSAlIHBcbiAgfVxuXG4gIHJldHVybiBQb2ludC5mcm9tQWZmaW5lKHRoaXMsIHgsIHkpXG59XG5cbkN1cnZlLnByb3RvdHlwZS5pc0luZmluaXR5ID0gZnVuY3Rpb24gKFEpIHtcbiAgaWYgKFEgPT09IHRoaXMuaW5maW5pdHkpIHJldHVybiB0cnVlXG5cbiAgcmV0dXJuIFEuei5zaWdudW0oKSA9PT0gMCAmJiBRLnkuc2lnbnVtKCkgIT09IDBcbn1cblxuQ3VydmUucHJvdG90eXBlLmlzT25DdXJ2ZSA9IGZ1bmN0aW9uIChRKSB7XG4gIGlmICh0aGlzLmlzSW5maW5pdHkoUSkpIHJldHVybiB0cnVlXG5cbiAgdmFyIHggPSBRLmFmZmluZVhcbiAgdmFyIHkgPSBRLmFmZmluZVlcbiAgdmFyIGEgPSB0aGlzLmFcbiAgdmFyIGIgPSB0aGlzLmJcbiAgdmFyIHAgPSB0aGlzLnBcblxuICAvLyBDaGVjayB0aGF0IHhRIGFuZCB5USBhcmUgaW50ZWdlcnMgaW4gdGhlIGludGVydmFsIFswLCBwIC0gMV1cbiAgaWYgKHguc2lnbnVtKCkgPCAwIHx8IHguY29tcGFyZVRvKHApID49IDApIHJldHVybiBmYWxzZVxuICBpZiAoeS5zaWdudW0oKSA8IDAgfHwgeS5jb21wYXJlVG8ocCkgPj0gMCkgcmV0dXJuIGZhbHNlXG5cbiAgLy8gYW5kIGNoZWNrIHRoYXQgeV4yID0geF4zICsgYXggKyBiIChtb2QgcClcbiAgdmFyIGxocyA9IHkuc3F1YXJlKCkubW9kKHApXG4gIHZhciByaHMgPSB4LnBvdygzKS5hZGQoYS5tdWx0aXBseSh4KSkuYWRkKGIpLm1vZChwKVxuICByZXR1cm4gbGhzLmVxdWFscyhyaHMpXG59XG5cbi8qKlxuICogVmFsaWRhdGUgYW4gZWxsaXB0aWMgY3VydmUgcG9pbnQuXG4gKlxuICogU2VlIFNFQyAxLCBzZWN0aW9uIDMuMi4yLjE6IEVsbGlwdGljIEN1cnZlIFB1YmxpYyBLZXkgVmFsaWRhdGlvbiBQcmltaXRpdmVcbiAqL1xuQ3VydmUucHJvdG90eXBlLnZhbGlkYXRlID0gZnVuY3Rpb24gKFEpIHtcbiAgLy8gQ2hlY2sgUSAhPSBPXG4gIGFzc2VydCghdGhpcy5pc0luZmluaXR5KFEpLCAnUG9pbnQgaXMgYXQgaW5maW5pdHknKVxuICBhc3NlcnQodGhpcy5pc09uQ3VydmUoUSksICdQb2ludCBpcyBub3Qgb24gdGhlIGN1cnZlJylcblxuICAvLyBDaGVjayBuUSA9IE8gKHdoZXJlIFEgaXMgYSBzY2FsYXIgbXVsdGlwbGUgb2YgRylcbiAgdmFyIG5RID0gUS5tdWx0aXBseSh0aGlzLm4pXG4gIGFzc2VydCh0aGlzLmlzSW5maW5pdHkoblEpLCAnUG9pbnQgaXMgbm90IGEgc2NhbGFyIG11bHRpcGxlIG9mIEcnKVxuXG4gIHJldHVybiB0cnVlXG59XG5cbm1vZHVsZS5leHBvcnRzID0gQ3VydmVcbiIsIm1vZHVsZS5leHBvcnRzPXtcbiAgXCJzZWNwMTI4cjFcIjoge1xuICAgIFwicFwiOiBcImZmZmZmZmZkZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmXCIsXG4gICAgXCJhXCI6IFwiZmZmZmZmZmRmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmNcIixcbiAgICBcImJcIjogXCJlODc1NzljMTEwNzlmNDNkZDgyNDk5M2MyY2VlNWVkM1wiLFxuICAgIFwiblwiOiBcImZmZmZmZmZlMDAwMDAwMDA3NWEzMGQxYjkwMzhhMTE1XCIsXG4gICAgXCJoXCI6IFwiMDFcIixcbiAgICBcIkd4XCI6IFwiMTYxZmY3NTI4Yjg5OWIyZDBjMjg2MDdjYTUyYzViODZcIixcbiAgICBcIkd5XCI6IFwiY2Y1YWM4Mzk1YmFmZWIxM2MwMmRhMjkyZGRlZDdhODNcIlxuICB9LFxuICBcInNlY3AxNjBrMVwiOiB7XG4gICAgXCJwXCI6IFwiZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmVmZmZmYWM3M1wiLFxuICAgIFwiYVwiOiBcIjAwXCIsXG4gICAgXCJiXCI6IFwiMDdcIixcbiAgICBcIm5cIjogXCIwMTAwMDAwMDAwMDAwMDAwMDAwMDAxYjhmYTE2ZGZhYjlhY2ExNmI2YjNcIixcbiAgICBcImhcIjogXCIwMVwiLFxuICAgIFwiR3hcIjogXCIzYjRjMzgyY2UzN2FhMTkyYTQwMTllNzYzMDM2ZjRmNWRkNGQ3ZWJiXCIsXG4gICAgXCJHeVwiOiBcIjkzOGNmOTM1MzE4ZmRjZWQ2YmMyODI4NjUzMTczM2MzZjAzYzRmZWVcIlxuICB9LFxuICBcInNlY3AxNjByMVwiOiB7XG4gICAgXCJwXCI6IFwiZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmY3ZmZmZmZmZlwiLFxuICAgIFwiYVwiOiBcImZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmN2ZmZmZmZmNcIixcbiAgICBcImJcIjogXCIxYzk3YmVmYzU0YmQ3YThiNjVhY2Y4OWY4MWQ0ZDRhZGM1NjVmYTQ1XCIsXG4gICAgXCJuXCI6IFwiMDEwMDAwMDAwMDAwMDAwMDAwMDAwMWY0YzhmOTI3YWVkM2NhNzUyMjU3XCIsXG4gICAgXCJoXCI6IFwiMDFcIixcbiAgICBcIkd4XCI6IFwiNGE5NmI1Njg4ZWY1NzMyODQ2NjQ2OTg5NjhjMzhiYjkxM2NiZmM4MlwiLFxuICAgIFwiR3lcIjogXCIyM2E2Mjg1NTMxNjg5NDdkNTlkY2M5MTIwNDIzNTEzNzdhYzVmYjMyXCJcbiAgfSxcbiAgXCJzZWNwMTkyazFcIjoge1xuICAgIFwicFwiOiBcImZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmVmZmZmZWUzN1wiLFxuICAgIFwiYVwiOiBcIjAwXCIsXG4gICAgXCJiXCI6IFwiMDNcIixcbiAgICBcIm5cIjogXCJmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmUyNmYyZmMxNzBmNjk0NjZhNzRkZWZkOGRcIixcbiAgICBcImhcIjogXCIwMVwiLFxuICAgIFwiR3hcIjogXCJkYjRmZjEwZWMwNTdlOWFlMjZiMDdkMDI4MGI3ZjQzNDFkYTVkMWIxZWFlMDZjN2RcIixcbiAgICBcIkd5XCI6IFwiOWIyZjJmNmQ5YzU2MjhhNzg0NDE2M2QwMTViZTg2MzQ0MDgyYWE4OGQ5NWUyZjlkXCJcbiAgfSxcbiAgXCJzZWNwMTkycjFcIjoge1xuICAgIFwicFwiOiBcImZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZlZmZmZmZmZmZmZmZmZmZmZlwiLFxuICAgIFwiYVwiOiBcImZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZlZmZmZmZmZmZmZmZmZmZmY1wiLFxuICAgIFwiYlwiOiBcIjY0MjEwNTE5ZTU5YzgwZTcwZmE3ZTlhYjcyMjQzMDQ5ZmViOGRlZWNjMTQ2YjliMVwiLFxuICAgIFwiblwiOiBcImZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZjk5ZGVmODM2MTQ2YmM5YjFiNGQyMjgzMVwiLFxuICAgIFwiaFwiOiBcIjAxXCIsXG4gICAgXCJHeFwiOiBcIjE4OGRhODBlYjAzMDkwZjY3Y2JmMjBlYjQzYTE4ODAwZjRmZjBhZmQ4MmZmMTAxMlwiLFxuICAgIFwiR3lcIjogXCIwNzE5MmI5NWZmYzhkYTc4NjMxMDExZWQ2YjI0Y2RkNTczZjk3N2ExMWU3OTQ4MTFcIlxuICB9LFxuICBcInNlY3AyNTZrMVwiOiB7XG4gICAgXCJwXCI6IFwiZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmVmZmZmZmMyZlwiLFxuICAgIFwiYVwiOiBcIjAwXCIsXG4gICAgXCJiXCI6IFwiMDdcIixcbiAgICBcIm5cIjogXCJmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZWJhYWVkY2U2YWY0OGEwM2JiZmQyNWU4Y2QwMzY0MTQxXCIsXG4gICAgXCJoXCI6IFwiMDFcIixcbiAgICBcIkd4XCI6IFwiNzliZTY2N2VmOWRjYmJhYzU1YTA2Mjk1Y2U4NzBiMDcwMjliZmNkYjJkY2UyOGQ5NTlmMjgxNWIxNmY4MTc5OFwiLFxuICAgIFwiR3lcIjogXCI0ODNhZGE3NzI2YTNjNDY1NWRhNGZiZmMwZTExMDhhOGZkMTdiNDQ4YTY4NTU0MTk5YzQ3ZDA4ZmZiMTBkNGI4XCJcbiAgfSxcbiAgXCJzZWNwMjU2cjFcIjoge1xuICAgIFwicFwiOiBcImZmZmZmZmZmMDAwMDAwMDEwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDBmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZcIixcbiAgICBcImFcIjogXCJmZmZmZmZmZjAwMDAwMDAxMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZjXCIsXG4gICAgXCJiXCI6IFwiNWFjNjM1ZDhhYTNhOTNlN2IzZWJiZDU1NzY5ODg2YmM2NTFkMDZiMGNjNTNiMGY2M2JjZTNjM2UyN2QyNjA0YlwiLFxuICAgIFwiblwiOiBcImZmZmZmZmZmMDAwMDAwMDBmZmZmZmZmZmZmZmZmZmZmYmNlNmZhYWRhNzE3OWU4NGYzYjljYWMyZmM2MzI1NTFcIixcbiAgICBcImhcIjogXCIwMVwiLFxuICAgIFwiR3hcIjogXCI2YjE3ZDFmMmUxMmM0MjQ3ZjhiY2U2ZTU2M2E0NDBmMjc3MDM3ZDgxMmRlYjMzYTBmNGExMzk0NWQ4OThjMjk2XCIsXG4gICAgXCJHeVwiOiBcIjRmZTM0MmUyZmUxYTdmOWI4ZWU3ZWI0YTdjMGY5ZTE2MmJjZTMzNTc2YjMxNWVjZWNiYjY0MDY4MzdiZjUxZjVcIlxuICB9XG59XG4iLCJ2YXIgUG9pbnQgPSByZXF1aXJlKCcuL3BvaW50JylcbnZhciBDdXJ2ZSA9IHJlcXVpcmUoJy4vY3VydmUnKVxuXG52YXIgZ2V0Q3VydmVCeU5hbWUgPSByZXF1aXJlKCcuL25hbWVzJylcblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIEN1cnZlOiBDdXJ2ZSxcbiAgUG9pbnQ6IFBvaW50LFxuICBnZXRDdXJ2ZUJ5TmFtZTogZ2V0Q3VydmVCeU5hbWVcbn1cbiIsInZhciBCaWdJbnRlZ2VyID0gcmVxdWlyZSgnYmlnaScpXG5cbnZhciBjdXJ2ZXMgPSByZXF1aXJlKCcuL2N1cnZlcy5qc29uJylcbnZhciBDdXJ2ZSA9IHJlcXVpcmUoJy4vY3VydmUnKVxuXG5mdW5jdGlvbiBnZXRDdXJ2ZUJ5TmFtZSAobmFtZSkge1xuICB2YXIgY3VydmUgPSBjdXJ2ZXNbbmFtZV1cbiAgaWYgKCFjdXJ2ZSkgcmV0dXJuIG51bGxcblxuICB2YXIgcCA9IG5ldyBCaWdJbnRlZ2VyKGN1cnZlLnAsIDE2KVxuICB2YXIgYSA9IG5ldyBCaWdJbnRlZ2VyKGN1cnZlLmEsIDE2KVxuICB2YXIgYiA9IG5ldyBCaWdJbnRlZ2VyKGN1cnZlLmIsIDE2KVxuICB2YXIgbiA9IG5ldyBCaWdJbnRlZ2VyKGN1cnZlLm4sIDE2KVxuICB2YXIgaCA9IG5ldyBCaWdJbnRlZ2VyKGN1cnZlLmgsIDE2KVxuICB2YXIgR3ggPSBuZXcgQmlnSW50ZWdlcihjdXJ2ZS5HeCwgMTYpXG4gIHZhciBHeSA9IG5ldyBCaWdJbnRlZ2VyKGN1cnZlLkd5LCAxNilcblxuICByZXR1cm4gbmV3IEN1cnZlKHAsIGEsIGIsIEd4LCBHeSwgbiwgaClcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBnZXRDdXJ2ZUJ5TmFtZVxuIiwidmFyIGFzc2VydCA9IHJlcXVpcmUoJ2Fzc2VydCcpXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnc2FmZS1idWZmZXInKS5CdWZmZXJcbnZhciBCaWdJbnRlZ2VyID0gcmVxdWlyZSgnYmlnaScpXG5cbnZhciBUSFJFRSA9IEJpZ0ludGVnZXIudmFsdWVPZigzKVxuXG5mdW5jdGlvbiBQb2ludCAoY3VydmUsIHgsIHksIHopIHtcbiAgYXNzZXJ0Lm5vdFN0cmljdEVxdWFsKHosIHVuZGVmaW5lZCwgJ01pc3NpbmcgWiBjb29yZGluYXRlJylcblxuICB0aGlzLmN1cnZlID0gY3VydmVcbiAgdGhpcy54ID0geFxuICB0aGlzLnkgPSB5XG4gIHRoaXMueiA9IHpcbiAgdGhpcy5fekludiA9IG51bGxcblxuICB0aGlzLmNvbXByZXNzZWQgPSB0cnVlXG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShQb2ludC5wcm90b3R5cGUsICd6SW52Jywge1xuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICBpZiAodGhpcy5fekludiA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5fekludiA9IHRoaXMuei5tb2RJbnZlcnNlKHRoaXMuY3VydmUucClcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5fekludlxuICB9XG59KVxuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoUG9pbnQucHJvdG90eXBlLCAnYWZmaW5lWCcsIHtcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMueC5tdWx0aXBseSh0aGlzLnpJbnYpLm1vZCh0aGlzLmN1cnZlLnApXG4gIH1cbn0pXG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShQb2ludC5wcm90b3R5cGUsICdhZmZpbmVZJywge1xuICBnZXQ6IGZ1bmN0aW9uICgpIHtcbiAgICByZXR1cm4gdGhpcy55Lm11bHRpcGx5KHRoaXMuekludikubW9kKHRoaXMuY3VydmUucClcbiAgfVxufSlcblxuUG9pbnQuZnJvbUFmZmluZSA9IGZ1bmN0aW9uIChjdXJ2ZSwgeCwgeSkge1xuICByZXR1cm4gbmV3IFBvaW50KGN1cnZlLCB4LCB5LCBCaWdJbnRlZ2VyLk9ORSlcbn1cblxuUG9pbnQucHJvdG90eXBlLmVxdWFscyA9IGZ1bmN0aW9uIChvdGhlcikge1xuICBpZiAob3RoZXIgPT09IHRoaXMpIHJldHVybiB0cnVlXG4gIGlmICh0aGlzLmN1cnZlLmlzSW5maW5pdHkodGhpcykpIHJldHVybiB0aGlzLmN1cnZlLmlzSW5maW5pdHkob3RoZXIpXG4gIGlmICh0aGlzLmN1cnZlLmlzSW5maW5pdHkob3RoZXIpKSByZXR1cm4gdGhpcy5jdXJ2ZS5pc0luZmluaXR5KHRoaXMpXG5cbiAgLy8gdSA9IFkyICogWjEgLSBZMSAqIFoyXG4gIHZhciB1ID0gb3RoZXIueS5tdWx0aXBseSh0aGlzLnopLnN1YnRyYWN0KHRoaXMueS5tdWx0aXBseShvdGhlci56KSkubW9kKHRoaXMuY3VydmUucClcblxuICBpZiAodS5zaWdudW0oKSAhPT0gMCkgcmV0dXJuIGZhbHNlXG5cbiAgLy8gdiA9IFgyICogWjEgLSBYMSAqIFoyXG4gIHZhciB2ID0gb3RoZXIueC5tdWx0aXBseSh0aGlzLnopLnN1YnRyYWN0KHRoaXMueC5tdWx0aXBseShvdGhlci56KSkubW9kKHRoaXMuY3VydmUucClcblxuICByZXR1cm4gdi5zaWdudW0oKSA9PT0gMFxufVxuXG5Qb2ludC5wcm90b3R5cGUubmVnYXRlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgeSA9IHRoaXMuY3VydmUucC5zdWJ0cmFjdCh0aGlzLnkpXG5cbiAgcmV0dXJuIG5ldyBQb2ludCh0aGlzLmN1cnZlLCB0aGlzLngsIHksIHRoaXMueilcbn1cblxuUG9pbnQucHJvdG90eXBlLmFkZCA9IGZ1bmN0aW9uIChiKSB7XG4gIGlmICh0aGlzLmN1cnZlLmlzSW5maW5pdHkodGhpcykpIHJldHVybiBiXG4gIGlmICh0aGlzLmN1cnZlLmlzSW5maW5pdHkoYikpIHJldHVybiB0aGlzXG5cbiAgdmFyIHgxID0gdGhpcy54XG4gIHZhciB5MSA9IHRoaXMueVxuICB2YXIgeDIgPSBiLnhcbiAgdmFyIHkyID0gYi55XG5cbiAgLy8gdSA9IFkyICogWjEgLSBZMSAqIFoyXG4gIHZhciB1ID0geTIubXVsdGlwbHkodGhpcy56KS5zdWJ0cmFjdCh5MS5tdWx0aXBseShiLnopKS5tb2QodGhpcy5jdXJ2ZS5wKVxuICAvLyB2ID0gWDIgKiBaMSAtIFgxICogWjJcbiAgdmFyIHYgPSB4Mi5tdWx0aXBseSh0aGlzLnopLnN1YnRyYWN0KHgxLm11bHRpcGx5KGIueikpLm1vZCh0aGlzLmN1cnZlLnApXG5cbiAgaWYgKHYuc2lnbnVtKCkgPT09IDApIHtcbiAgICBpZiAodS5zaWdudW0oKSA9PT0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMudHdpY2UoKSAvLyB0aGlzID09IGIsIHNvIGRvdWJsZVxuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmN1cnZlLmluZmluaXR5IC8vIHRoaXMgPSAtYiwgc28gaW5maW5pdHlcbiAgfVxuXG4gIHZhciB2MiA9IHYuc3F1YXJlKClcbiAgdmFyIHYzID0gdjIubXVsdGlwbHkodilcbiAgdmFyIHgxdjIgPSB4MS5tdWx0aXBseSh2MilcbiAgdmFyIHp1MiA9IHUuc3F1YXJlKCkubXVsdGlwbHkodGhpcy56KVxuXG4gIC8vIHgzID0gdiAqICh6MiAqICh6MSAqIHVeMiAtIDIgKiB4MSAqIHZeMikgLSB2XjMpXG4gIHZhciB4MyA9IHp1Mi5zdWJ0cmFjdCh4MXYyLnNoaWZ0TGVmdCgxKSkubXVsdGlwbHkoYi56KS5zdWJ0cmFjdCh2MykubXVsdGlwbHkodikubW9kKHRoaXMuY3VydmUucClcbiAgLy8geTMgPSB6MiAqICgzICogeDEgKiB1ICogdl4yIC0geTEgKiB2XjMgLSB6MSAqIHVeMykgKyB1ICogdl4zXG4gIHZhciB5MyA9IHgxdjIubXVsdGlwbHkoVEhSRUUpLm11bHRpcGx5KHUpLnN1YnRyYWN0KHkxLm11bHRpcGx5KHYzKSkuc3VidHJhY3QoenUyLm11bHRpcGx5KHUpKS5tdWx0aXBseShiLnopLmFkZCh1Lm11bHRpcGx5KHYzKSkubW9kKHRoaXMuY3VydmUucClcbiAgLy8gejMgPSB2XjMgKiB6MSAqIHoyXG4gIHZhciB6MyA9IHYzLm11bHRpcGx5KHRoaXMueikubXVsdGlwbHkoYi56KS5tb2QodGhpcy5jdXJ2ZS5wKVxuXG4gIHJldHVybiBuZXcgUG9pbnQodGhpcy5jdXJ2ZSwgeDMsIHkzLCB6Mylcbn1cblxuUG9pbnQucHJvdG90eXBlLnR3aWNlID0gZnVuY3Rpb24gKCkge1xuICBpZiAodGhpcy5jdXJ2ZS5pc0luZmluaXR5KHRoaXMpKSByZXR1cm4gdGhpc1xuICBpZiAodGhpcy55LnNpZ251bSgpID09PSAwKSByZXR1cm4gdGhpcy5jdXJ2ZS5pbmZpbml0eVxuXG4gIHZhciB4MSA9IHRoaXMueFxuICB2YXIgeTEgPSB0aGlzLnlcblxuICB2YXIgeTF6MSA9IHkxLm11bHRpcGx5KHRoaXMueikubW9kKHRoaXMuY3VydmUucClcbiAgdmFyIHkxc3F6MSA9IHkxejEubXVsdGlwbHkoeTEpLm1vZCh0aGlzLmN1cnZlLnApXG4gIHZhciBhID0gdGhpcy5jdXJ2ZS5hXG5cbiAgLy8gdyA9IDMgKiB4MV4yICsgYSAqIHoxXjJcbiAgdmFyIHcgPSB4MS5zcXVhcmUoKS5tdWx0aXBseShUSFJFRSlcblxuICBpZiAoYS5zaWdudW0oKSAhPT0gMCkge1xuICAgIHcgPSB3LmFkZCh0aGlzLnouc3F1YXJlKCkubXVsdGlwbHkoYSkpXG4gIH1cblxuICB3ID0gdy5tb2QodGhpcy5jdXJ2ZS5wKVxuICAvLyB4MyA9IDIgKiB5MSAqIHoxICogKHdeMiAtIDggKiB4MSAqIHkxXjIgKiB6MSlcbiAgdmFyIHgzID0gdy5zcXVhcmUoKS5zdWJ0cmFjdCh4MS5zaGlmdExlZnQoMykubXVsdGlwbHkoeTFzcXoxKSkuc2hpZnRMZWZ0KDEpLm11bHRpcGx5KHkxejEpLm1vZCh0aGlzLmN1cnZlLnApXG4gIC8vIHkzID0gNCAqIHkxXjIgKiB6MSAqICgzICogdyAqIHgxIC0gMiAqIHkxXjIgKiB6MSkgLSB3XjNcbiAgdmFyIHkzID0gdy5tdWx0aXBseShUSFJFRSkubXVsdGlwbHkoeDEpLnN1YnRyYWN0KHkxc3F6MS5zaGlmdExlZnQoMSkpLnNoaWZ0TGVmdCgyKS5tdWx0aXBseSh5MXNxejEpLnN1YnRyYWN0KHcucG93KDMpKS5tb2QodGhpcy5jdXJ2ZS5wKVxuICAvLyB6MyA9IDggKiAoeTEgKiB6MSleM1xuICB2YXIgejMgPSB5MXoxLnBvdygzKS5zaGlmdExlZnQoMykubW9kKHRoaXMuY3VydmUucClcblxuICByZXR1cm4gbmV3IFBvaW50KHRoaXMuY3VydmUsIHgzLCB5MywgejMpXG59XG5cbi8vIFNpbXBsZSBOQUYgKE5vbi1BZGphY2VudCBGb3JtKSBtdWx0aXBsaWNhdGlvbiBhbGdvcml0aG1cbi8vIFRPRE86IG1vZHVsYXJpemUgdGhlIG11bHRpcGxpY2F0aW9uIGFsZ29yaXRobVxuUG9pbnQucHJvdG90eXBlLm11bHRpcGx5ID0gZnVuY3Rpb24gKGspIHtcbiAgaWYgKHRoaXMuY3VydmUuaXNJbmZpbml0eSh0aGlzKSkgcmV0dXJuIHRoaXNcbiAgaWYgKGsuc2lnbnVtKCkgPT09IDApIHJldHVybiB0aGlzLmN1cnZlLmluZmluaXR5XG5cbiAgdmFyIGUgPSBrXG4gIHZhciBoID0gZS5tdWx0aXBseShUSFJFRSlcblxuICB2YXIgbmVnID0gdGhpcy5uZWdhdGUoKVxuICB2YXIgUiA9IHRoaXNcblxuICBmb3IgKHZhciBpID0gaC5iaXRMZW5ndGgoKSAtIDI7IGkgPiAwOyAtLWkpIHtcbiAgICB2YXIgaEJpdCA9IGgudGVzdEJpdChpKVxuICAgIHZhciBlQml0ID0gZS50ZXN0Qml0KGkpXG5cbiAgICBSID0gUi50d2ljZSgpXG5cbiAgICBpZiAoaEJpdCAhPT0gZUJpdCkge1xuICAgICAgUiA9IFIuYWRkKGhCaXQgPyB0aGlzIDogbmVnKVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiBSXG59XG5cbi8vIENvbXB1dGUgdGhpcypqICsgeCprIChzaW11bHRhbmVvdXMgbXVsdGlwbGljYXRpb24pXG5Qb2ludC5wcm90b3R5cGUubXVsdGlwbHlUd28gPSBmdW5jdGlvbiAoaiwgeCwgaykge1xuICB2YXIgaSA9IE1hdGgubWF4KGouYml0TGVuZ3RoKCksIGsuYml0TGVuZ3RoKCkpIC0gMVxuICB2YXIgUiA9IHRoaXMuY3VydmUuaW5maW5pdHlcbiAgdmFyIGJvdGggPSB0aGlzLmFkZCh4KVxuXG4gIHdoaWxlIChpID49IDApIHtcbiAgICB2YXIgakJpdCA9IGoudGVzdEJpdChpKVxuICAgIHZhciBrQml0ID0gay50ZXN0Qml0KGkpXG5cbiAgICBSID0gUi50d2ljZSgpXG5cbiAgICBpZiAoakJpdCkge1xuICAgICAgaWYgKGtCaXQpIHtcbiAgICAgICAgUiA9IFIuYWRkKGJvdGgpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBSID0gUi5hZGQodGhpcylcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGtCaXQpIHtcbiAgICAgIFIgPSBSLmFkZCh4KVxuICAgIH1cbiAgICAtLWlcbiAgfVxuXG4gIHJldHVybiBSXG59XG5cblBvaW50LnByb3RvdHlwZS5nZXRFbmNvZGVkID0gZnVuY3Rpb24gKGNvbXByZXNzZWQpIHtcbiAgaWYgKGNvbXByZXNzZWQgPT0gbnVsbCkgY29tcHJlc3NlZCA9IHRoaXMuY29tcHJlc3NlZFxuICBpZiAodGhpcy5jdXJ2ZS5pc0luZmluaXR5KHRoaXMpKSByZXR1cm4gQnVmZmVyLmFsbG9jKDEsIDApIC8vIEluZmluaXR5IHBvaW50IGVuY29kZWQgaXMgc2ltcGx5ICcwMCdcblxuICB2YXIgeCA9IHRoaXMuYWZmaW5lWFxuICB2YXIgeSA9IHRoaXMuYWZmaW5lWVxuICB2YXIgYnl0ZUxlbmd0aCA9IHRoaXMuY3VydmUucExlbmd0aFxuICB2YXIgYnVmZmVyXG5cbiAgLy8gMHgwMi8weDAzIHwgWFxuICBpZiAoY29tcHJlc3NlZCkge1xuICAgIGJ1ZmZlciA9IEJ1ZmZlci5hbGxvY1Vuc2FmZSgxICsgYnl0ZUxlbmd0aClcbiAgICBidWZmZXIud3JpdGVVSW50OCh5LmlzRXZlbigpID8gMHgwMiA6IDB4MDMsIDApXG5cbiAgLy8gMHgwNCB8IFggfCBZXG4gIH0gZWxzZSB7XG4gICAgYnVmZmVyID0gQnVmZmVyLmFsbG9jVW5zYWZlKDEgKyBieXRlTGVuZ3RoICsgYnl0ZUxlbmd0aClcbiAgICBidWZmZXIud3JpdGVVSW50OCgweDA0LCAwKVxuXG4gICAgeS50b0J1ZmZlcihieXRlTGVuZ3RoKS5jb3B5KGJ1ZmZlciwgMSArIGJ5dGVMZW5ndGgpXG4gIH1cblxuICB4LnRvQnVmZmVyKGJ5dGVMZW5ndGgpLmNvcHkoYnVmZmVyLCAxKVxuXG4gIHJldHVybiBidWZmZXJcbn1cblxuUG9pbnQuZGVjb2RlRnJvbSA9IGZ1bmN0aW9uIChjdXJ2ZSwgYnVmZmVyKSB7XG4gIHZhciB0eXBlID0gYnVmZmVyLnJlYWRVSW50OCgwKVxuICB2YXIgY29tcHJlc3NlZCA9ICh0eXBlICE9PSA0KVxuXG4gIHZhciBieXRlTGVuZ3RoID0gTWF0aC5mbG9vcigoY3VydmUucC5iaXRMZW5ndGgoKSArIDcpIC8gOClcbiAgdmFyIHggPSBCaWdJbnRlZ2VyLmZyb21CdWZmZXIoYnVmZmVyLnNsaWNlKDEsIDEgKyBieXRlTGVuZ3RoKSlcblxuICB2YXIgUVxuICBpZiAoY29tcHJlc3NlZCkge1xuICAgIGFzc2VydC5lcXVhbChidWZmZXIubGVuZ3RoLCBieXRlTGVuZ3RoICsgMSwgJ0ludmFsaWQgc2VxdWVuY2UgbGVuZ3RoJylcbiAgICBhc3NlcnQodHlwZSA9PT0gMHgwMiB8fCB0eXBlID09PSAweDAzLCAnSW52YWxpZCBzZXF1ZW5jZSB0YWcnKVxuXG4gICAgdmFyIGlzT2RkID0gKHR5cGUgPT09IDB4MDMpXG4gICAgUSA9IGN1cnZlLnBvaW50RnJvbVgoaXNPZGQsIHgpXG4gIH0gZWxzZSB7XG4gICAgYXNzZXJ0LmVxdWFsKGJ1ZmZlci5sZW5ndGgsIDEgKyBieXRlTGVuZ3RoICsgYnl0ZUxlbmd0aCwgJ0ludmFsaWQgc2VxdWVuY2UgbGVuZ3RoJylcblxuICAgIHZhciB5ID0gQmlnSW50ZWdlci5mcm9tQnVmZmVyKGJ1ZmZlci5zbGljZSgxICsgYnl0ZUxlbmd0aCkpXG4gICAgUSA9IFBvaW50LmZyb21BZmZpbmUoY3VydmUsIHgsIHkpXG4gIH1cblxuICBRLmNvbXByZXNzZWQgPSBjb21wcmVzc2VkXG4gIHJldHVybiBRXG59XG5cblBvaW50LnByb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKHRoaXMuY3VydmUuaXNJbmZpbml0eSh0aGlzKSkgcmV0dXJuICcoSU5GSU5JVFkpJ1xuXG4gIHJldHVybiAnKCcgKyB0aGlzLmFmZmluZVgudG9TdHJpbmcoKSArICcsJyArIHRoaXMuYWZmaW5lWS50b1N0cmluZygpICsgJyknXG59XG5cbm1vZHVsZS5leHBvcnRzID0gUG9pbnRcbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG5mdW5jdGlvbiBFdmVudEVtaXR0ZXIoKSB7XG4gIHRoaXMuX2V2ZW50cyA9IHRoaXMuX2V2ZW50cyB8fCB7fTtcbiAgdGhpcy5fbWF4TGlzdGVuZXJzID0gdGhpcy5fbWF4TGlzdGVuZXJzIHx8IHVuZGVmaW5lZDtcbn1cbm1vZHVsZS5leHBvcnRzID0gRXZlbnRFbWl0dGVyO1xuXG4vLyBCYWNrd2FyZHMtY29tcGF0IHdpdGggbm9kZSAwLjEwLnhcbkV2ZW50RW1pdHRlci5FdmVudEVtaXR0ZXIgPSBFdmVudEVtaXR0ZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX2V2ZW50cyA9IHVuZGVmaW5lZDtcbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuX21heExpc3RlbmVycyA9IHVuZGVmaW5lZDtcblxuLy8gQnkgZGVmYXVsdCBFdmVudEVtaXR0ZXJzIHdpbGwgcHJpbnQgYSB3YXJuaW5nIGlmIG1vcmUgdGhhbiAxMCBsaXN0ZW5lcnMgYXJlXG4vLyBhZGRlZCB0byBpdC4gVGhpcyBpcyBhIHVzZWZ1bCBkZWZhdWx0IHdoaWNoIGhlbHBzIGZpbmRpbmcgbWVtb3J5IGxlYWtzLlxuRXZlbnRFbWl0dGVyLmRlZmF1bHRNYXhMaXN0ZW5lcnMgPSAxMDtcblxuLy8gT2J2aW91c2x5IG5vdCBhbGwgRW1pdHRlcnMgc2hvdWxkIGJlIGxpbWl0ZWQgdG8gMTAuIFRoaXMgZnVuY3Rpb24gYWxsb3dzXG4vLyB0aGF0IHRvIGJlIGluY3JlYXNlZC4gU2V0IHRvIHplcm8gZm9yIHVubGltaXRlZC5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUuc2V0TWF4TGlzdGVuZXJzID0gZnVuY3Rpb24obikge1xuICBpZiAoIWlzTnVtYmVyKG4pIHx8IG4gPCAwIHx8IGlzTmFOKG4pKVxuICAgIHRocm93IFR5cGVFcnJvcignbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gIHRoaXMuX21heExpc3RlbmVycyA9IG47XG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5lbWl0ID0gZnVuY3Rpb24odHlwZSkge1xuICB2YXIgZXIsIGhhbmRsZXIsIGxlbiwgYXJncywgaSwgbGlzdGVuZXJzO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzKVxuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuXG4gIC8vIElmIHRoZXJlIGlzIG5vICdlcnJvcicgZXZlbnQgbGlzdGVuZXIgdGhlbiB0aHJvdy5cbiAgaWYgKHR5cGUgPT09ICdlcnJvcicpIHtcbiAgICBpZiAoIXRoaXMuX2V2ZW50cy5lcnJvciB8fFxuICAgICAgICAoaXNPYmplY3QodGhpcy5fZXZlbnRzLmVycm9yKSAmJiAhdGhpcy5fZXZlbnRzLmVycm9yLmxlbmd0aCkpIHtcbiAgICAgIGVyID0gYXJndW1lbnRzWzFdO1xuICAgICAgaWYgKGVyIGluc3RhbmNlb2YgRXJyb3IpIHtcbiAgICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCAnZXJyb3InIGV2ZW50XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBBdCBsZWFzdCBnaXZlIHNvbWUga2luZCBvZiBjb250ZXh0IHRvIHRoZSB1c2VyXG4gICAgICAgIHZhciBlcnIgPSBuZXcgRXJyb3IoJ1VuY2F1Z2h0LCB1bnNwZWNpZmllZCBcImVycm9yXCIgZXZlbnQuICgnICsgZXIgKyAnKScpO1xuICAgICAgICBlcnIuY29udGV4dCA9IGVyO1xuICAgICAgICB0aHJvdyBlcnI7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaGFuZGxlciA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcblxuICBpZiAoaXNVbmRlZmluZWQoaGFuZGxlcikpXG4gICAgcmV0dXJuIGZhbHNlO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGhhbmRsZXIpKSB7XG4gICAgc3dpdGNoIChhcmd1bWVudHMubGVuZ3RoKSB7XG4gICAgICAvLyBmYXN0IGNhc2VzXG4gICAgICBjYXNlIDE6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI6XG4gICAgICAgIGhhbmRsZXIuY2FsbCh0aGlzLCBhcmd1bWVudHNbMV0pO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMzpcbiAgICAgICAgaGFuZGxlci5jYWxsKHRoaXMsIGFyZ3VtZW50c1sxXSwgYXJndW1lbnRzWzJdKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICAvLyBzbG93ZXJcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgICAgICBoYW5kbGVyLmFwcGx5KHRoaXMsIGFyZ3MpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpc09iamVjdChoYW5kbGVyKSkge1xuICAgIGFyZ3MgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuICAgIGxpc3RlbmVycyA9IGhhbmRsZXIuc2xpY2UoKTtcbiAgICBsZW4gPSBsaXN0ZW5lcnMubGVuZ3RoO1xuICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgIGxpc3RlbmVyc1tpXS5hcHBseSh0aGlzLCBhcmdzKTtcbiAgfVxuXG4gIHJldHVybiB0cnVlO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIHZhciBtO1xuXG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICB0aGlzLl9ldmVudHMgPSB7fTtcblxuICAvLyBUbyBhdm9pZCByZWN1cnNpb24gaW4gdGhlIGNhc2UgdGhhdCB0eXBlID09PSBcIm5ld0xpc3RlbmVyXCIhIEJlZm9yZVxuICAvLyBhZGRpbmcgaXQgdG8gdGhlIGxpc3RlbmVycywgZmlyc3QgZW1pdCBcIm5ld0xpc3RlbmVyXCIuXG4gIGlmICh0aGlzLl9ldmVudHMubmV3TGlzdGVuZXIpXG4gICAgdGhpcy5lbWl0KCduZXdMaXN0ZW5lcicsIHR5cGUsXG4gICAgICAgICAgICAgIGlzRnVuY3Rpb24obGlzdGVuZXIubGlzdGVuZXIpID9cbiAgICAgICAgICAgICAgbGlzdGVuZXIubGlzdGVuZXIgOiBsaXN0ZW5lcik7XG5cbiAgaWYgKCF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgLy8gT3B0aW1pemUgdGhlIGNhc2Ugb2Ygb25lIGxpc3RlbmVyLiBEb24ndCBuZWVkIHRoZSBleHRyYSBhcnJheSBvYmplY3QuXG4gICAgdGhpcy5fZXZlbnRzW3R5cGVdID0gbGlzdGVuZXI7XG4gIGVsc2UgaWYgKGlzT2JqZWN0KHRoaXMuX2V2ZW50c1t0eXBlXSkpXG4gICAgLy8gSWYgd2UndmUgYWxyZWFkeSBnb3QgYW4gYXJyYXksIGp1c3QgYXBwZW5kLlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGxpc3RlbmVyKTtcbiAgZWxzZVxuICAgIC8vIEFkZGluZyB0aGUgc2Vjb25kIGVsZW1lbnQsIG5lZWQgdG8gY2hhbmdlIHRvIGFycmF5LlxuICAgIHRoaXMuX2V2ZW50c1t0eXBlXSA9IFt0aGlzLl9ldmVudHNbdHlwZV0sIGxpc3RlbmVyXTtcblxuICAvLyBDaGVjayBmb3IgbGlzdGVuZXIgbGVha1xuICBpZiAoaXNPYmplY3QodGhpcy5fZXZlbnRzW3R5cGVdKSAmJiAhdGhpcy5fZXZlbnRzW3R5cGVdLndhcm5lZCkge1xuICAgIGlmICghaXNVbmRlZmluZWQodGhpcy5fbWF4TGlzdGVuZXJzKSkge1xuICAgICAgbSA9IHRoaXMuX21heExpc3RlbmVycztcbiAgICB9IGVsc2Uge1xuICAgICAgbSA9IEV2ZW50RW1pdHRlci5kZWZhdWx0TWF4TGlzdGVuZXJzO1xuICAgIH1cblxuICAgIGlmIChtICYmIG0gPiAwICYmIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGggPiBtKSB7XG4gICAgICB0aGlzLl9ldmVudHNbdHlwZV0ud2FybmVkID0gdHJ1ZTtcbiAgICAgIGNvbnNvbGUuZXJyb3IoJyhub2RlKSB3YXJuaW5nOiBwb3NzaWJsZSBFdmVudEVtaXR0ZXIgbWVtb3J5ICcgK1xuICAgICAgICAgICAgICAgICAgICAnbGVhayBkZXRlY3RlZC4gJWQgbGlzdGVuZXJzIGFkZGVkLiAnICtcbiAgICAgICAgICAgICAgICAgICAgJ1VzZSBlbWl0dGVyLnNldE1heExpc3RlbmVycygpIHRvIGluY3JlYXNlIGxpbWl0LicsXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGgpO1xuICAgICAgaWYgKHR5cGVvZiBjb25zb2xlLnRyYWNlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIC8vIG5vdCBzdXBwb3J0ZWQgaW4gSUUgMTBcbiAgICAgICAgY29uc29sZS50cmFjZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5vbiA9IEV2ZW50RW1pdHRlci5wcm90b3R5cGUuYWRkTGlzdGVuZXI7XG5cbkV2ZW50RW1pdHRlci5wcm90b3R5cGUub25jZSA9IGZ1bmN0aW9uKHR5cGUsIGxpc3RlbmVyKSB7XG4gIGlmICghaXNGdW5jdGlvbihsaXN0ZW5lcikpXG4gICAgdGhyb3cgVHlwZUVycm9yKCdsaXN0ZW5lciBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcblxuICB2YXIgZmlyZWQgPSBmYWxzZTtcblxuICBmdW5jdGlvbiBnKCkge1xuICAgIHRoaXMucmVtb3ZlTGlzdGVuZXIodHlwZSwgZyk7XG5cbiAgICBpZiAoIWZpcmVkKSB7XG4gICAgICBmaXJlZCA9IHRydWU7XG4gICAgICBsaXN0ZW5lci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgfVxuXG4gIGcubGlzdGVuZXIgPSBsaXN0ZW5lcjtcbiAgdGhpcy5vbih0eXBlLCBnKTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbi8vIGVtaXRzIGEgJ3JlbW92ZUxpc3RlbmVyJyBldmVudCBpZmYgdGhlIGxpc3RlbmVyIHdhcyByZW1vdmVkXG5FdmVudEVtaXR0ZXIucHJvdG90eXBlLnJlbW92ZUxpc3RlbmVyID0gZnVuY3Rpb24odHlwZSwgbGlzdGVuZXIpIHtcbiAgdmFyIGxpc3QsIHBvc2l0aW9uLCBsZW5ndGgsIGk7XG5cbiAgaWYgKCFpc0Z1bmN0aW9uKGxpc3RlbmVyKSlcbiAgICB0aHJvdyBUeXBlRXJyb3IoJ2xpc3RlbmVyIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuXG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0dXJuIHRoaXM7XG5cbiAgbGlzdCA9IHRoaXMuX2V2ZW50c1t0eXBlXTtcbiAgbGVuZ3RoID0gbGlzdC5sZW5ndGg7XG4gIHBvc2l0aW9uID0gLTE7XG5cbiAgaWYgKGxpc3QgPT09IGxpc3RlbmVyIHx8XG4gICAgICAoaXNGdW5jdGlvbihsaXN0Lmxpc3RlbmVyKSAmJiBsaXN0Lmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIGlmICh0aGlzLl9ldmVudHMucmVtb3ZlTGlzdGVuZXIpXG4gICAgICB0aGlzLmVtaXQoJ3JlbW92ZUxpc3RlbmVyJywgdHlwZSwgbGlzdGVuZXIpO1xuXG4gIH0gZWxzZSBpZiAoaXNPYmplY3QobGlzdCkpIHtcbiAgICBmb3IgKGkgPSBsZW5ndGg7IGktLSA+IDA7KSB7XG4gICAgICBpZiAobGlzdFtpXSA9PT0gbGlzdGVuZXIgfHxcbiAgICAgICAgICAobGlzdFtpXS5saXN0ZW5lciAmJiBsaXN0W2ldLmxpc3RlbmVyID09PSBsaXN0ZW5lcikpIHtcbiAgICAgICAgcG9zaXRpb24gPSBpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAocG9zaXRpb24gPCAwKVxuICAgICAgcmV0dXJuIHRoaXM7XG5cbiAgICBpZiAobGlzdC5sZW5ndGggPT09IDEpIHtcbiAgICAgIGxpc3QubGVuZ3RoID0gMDtcbiAgICAgIGRlbGV0ZSB0aGlzLl9ldmVudHNbdHlwZV07XG4gICAgfSBlbHNlIHtcbiAgICAgIGxpc3Quc3BsaWNlKHBvc2l0aW9uLCAxKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKVxuICAgICAgdGhpcy5lbWl0KCdyZW1vdmVMaXN0ZW5lcicsIHR5cGUsIGxpc3RlbmVyKTtcbiAgfVxuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5yZW1vdmVBbGxMaXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciBrZXksIGxpc3RlbmVycztcblxuICBpZiAoIXRoaXMuX2V2ZW50cylcbiAgICByZXR1cm4gdGhpcztcblxuICAvLyBub3QgbGlzdGVuaW5nIGZvciByZW1vdmVMaXN0ZW5lciwgbm8gbmVlZCB0byBlbWl0XG4gIGlmICghdGhpcy5fZXZlbnRzLnJlbW92ZUxpc3RlbmVyKSB7XG4gICAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPT09IDApXG4gICAgICB0aGlzLl9ldmVudHMgPSB7fTtcbiAgICBlbHNlIGlmICh0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gZW1pdCByZW1vdmVMaXN0ZW5lciBmb3IgYWxsIGxpc3RlbmVycyBvbiBhbGwgZXZlbnRzXG4gIGlmIChhcmd1bWVudHMubGVuZ3RoID09PSAwKSB7XG4gICAgZm9yIChrZXkgaW4gdGhpcy5fZXZlbnRzKSB7XG4gICAgICBpZiAoa2V5ID09PSAncmVtb3ZlTGlzdGVuZXInKSBjb250aW51ZTtcbiAgICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKGtleSk7XG4gICAgfVxuICAgIHRoaXMucmVtb3ZlQWxsTGlzdGVuZXJzKCdyZW1vdmVMaXN0ZW5lcicpO1xuICAgIHRoaXMuX2V2ZW50cyA9IHt9O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgbGlzdGVuZXJzID0gdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIGlmIChpc0Z1bmN0aW9uKGxpc3RlbmVycykpIHtcbiAgICB0aGlzLnJlbW92ZUxpc3RlbmVyKHR5cGUsIGxpc3RlbmVycyk7XG4gIH0gZWxzZSBpZiAobGlzdGVuZXJzKSB7XG4gICAgLy8gTElGTyBvcmRlclxuICAgIHdoaWxlIChsaXN0ZW5lcnMubGVuZ3RoKVxuICAgICAgdGhpcy5yZW1vdmVMaXN0ZW5lcih0eXBlLCBsaXN0ZW5lcnNbbGlzdGVuZXJzLmxlbmd0aCAtIDFdKTtcbiAgfVxuICBkZWxldGUgdGhpcy5fZXZlbnRzW3R5cGVdO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lcnMgPSBmdW5jdGlvbih0eXBlKSB7XG4gIHZhciByZXQ7XG4gIGlmICghdGhpcy5fZXZlbnRzIHx8ICF0aGlzLl9ldmVudHNbdHlwZV0pXG4gICAgcmV0ID0gW107XG4gIGVsc2UgaWYgKGlzRnVuY3Rpb24odGhpcy5fZXZlbnRzW3R5cGVdKSlcbiAgICByZXQgPSBbdGhpcy5fZXZlbnRzW3R5cGVdXTtcbiAgZWxzZVxuICAgIHJldCA9IHRoaXMuX2V2ZW50c1t0eXBlXS5zbGljZSgpO1xuICByZXR1cm4gcmV0O1xufTtcblxuRXZlbnRFbWl0dGVyLnByb3RvdHlwZS5saXN0ZW5lckNvdW50ID0gZnVuY3Rpb24odHlwZSkge1xuICBpZiAodGhpcy5fZXZlbnRzKSB7XG4gICAgdmFyIGV2bGlzdGVuZXIgPSB0aGlzLl9ldmVudHNbdHlwZV07XG5cbiAgICBpZiAoaXNGdW5jdGlvbihldmxpc3RlbmVyKSlcbiAgICAgIHJldHVybiAxO1xuICAgIGVsc2UgaWYgKGV2bGlzdGVuZXIpXG4gICAgICByZXR1cm4gZXZsaXN0ZW5lci5sZW5ndGg7XG4gIH1cbiAgcmV0dXJuIDA7XG59O1xuXG5FdmVudEVtaXR0ZXIubGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uKGVtaXR0ZXIsIHR5cGUpIHtcbiAgcmV0dXJuIGVtaXR0ZXIubGlzdGVuZXJDb3VudCh0eXBlKTtcbn07XG5cbmZ1bmN0aW9uIGlzRnVuY3Rpb24oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnZnVuY3Rpb24nO1xufVxuXG5mdW5jdGlvbiBpc051bWJlcihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdudW1iZXInO1xufVxuXG5mdW5jdGlvbiBpc09iamVjdChhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdvYmplY3QnICYmIGFyZyAhPT0gbnVsbDtcbn1cblxuZnVuY3Rpb24gaXNVbmRlZmluZWQoYXJnKSB7XG4gIHJldHVybiBhcmcgPT09IHZvaWQgMDtcbn1cbiIsIid1c2Ugc3RyaWN0J1xudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyXG52YXIgVHJhbnNmb3JtID0gcmVxdWlyZSgnc3RyZWFtJykuVHJhbnNmb3JtXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpXG5cbmZ1bmN0aW9uIHRocm93SWZOb3RTdHJpbmdPckJ1ZmZlciAodmFsLCBwcmVmaXgpIHtcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIodmFsKSAmJiB0eXBlb2YgdmFsICE9PSAnc3RyaW5nJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IocHJlZml4ICsgJyBtdXN0IGJlIGEgc3RyaW5nIG9yIGEgYnVmZmVyJylcbiAgfVxufVxuXG5mdW5jdGlvbiBIYXNoQmFzZSAoYmxvY2tTaXplKSB7XG4gIFRyYW5zZm9ybS5jYWxsKHRoaXMpXG5cbiAgdGhpcy5fYmxvY2sgPSBCdWZmZXIuYWxsb2NVbnNhZmUoYmxvY2tTaXplKVxuICB0aGlzLl9ibG9ja1NpemUgPSBibG9ja1NpemVcbiAgdGhpcy5fYmxvY2tPZmZzZXQgPSAwXG4gIHRoaXMuX2xlbmd0aCA9IFswLCAwLCAwLCAwXVxuXG4gIHRoaXMuX2ZpbmFsaXplZCA9IGZhbHNlXG59XG5cbmluaGVyaXRzKEhhc2hCYXNlLCBUcmFuc2Zvcm0pXG5cbkhhc2hCYXNlLnByb3RvdHlwZS5fdHJhbnNmb3JtID0gZnVuY3Rpb24gKGNodW5rLCBlbmNvZGluZywgY2FsbGJhY2spIHtcbiAgdmFyIGVycm9yID0gbnVsbFxuICB0cnkge1xuICAgIHRoaXMudXBkYXRlKGNodW5rLCBlbmNvZGluZylcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgZXJyb3IgPSBlcnJcbiAgfVxuXG4gIGNhbGxiYWNrKGVycm9yKVxufVxuXG5IYXNoQmFzZS5wcm90b3R5cGUuX2ZsdXNoID0gZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gIHZhciBlcnJvciA9IG51bGxcbiAgdHJ5IHtcbiAgICB0aGlzLnB1c2godGhpcy5kaWdlc3QoKSlcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgZXJyb3IgPSBlcnJcbiAgfVxuXG4gIGNhbGxiYWNrKGVycm9yKVxufVxuXG5IYXNoQmFzZS5wcm90b3R5cGUudXBkYXRlID0gZnVuY3Rpb24gKGRhdGEsIGVuY29kaW5nKSB7XG4gIHRocm93SWZOb3RTdHJpbmdPckJ1ZmZlcihkYXRhLCAnRGF0YScpXG4gIGlmICh0aGlzLl9maW5hbGl6ZWQpIHRocm93IG5ldyBFcnJvcignRGlnZXN0IGFscmVhZHkgY2FsbGVkJylcbiAgaWYgKCFCdWZmZXIuaXNCdWZmZXIoZGF0YSkpIGRhdGEgPSBCdWZmZXIuZnJvbShkYXRhLCBlbmNvZGluZylcblxuICAvLyBjb25zdW1lIGRhdGFcbiAgdmFyIGJsb2NrID0gdGhpcy5fYmxvY2tcbiAgdmFyIG9mZnNldCA9IDBcbiAgd2hpbGUgKHRoaXMuX2Jsb2NrT2Zmc2V0ICsgZGF0YS5sZW5ndGggLSBvZmZzZXQgPj0gdGhpcy5fYmxvY2tTaXplKSB7XG4gICAgZm9yICh2YXIgaSA9IHRoaXMuX2Jsb2NrT2Zmc2V0OyBpIDwgdGhpcy5fYmxvY2tTaXplOykgYmxvY2tbaSsrXSA9IGRhdGFbb2Zmc2V0KytdXG4gICAgdGhpcy5fdXBkYXRlKClcbiAgICB0aGlzLl9ibG9ja09mZnNldCA9IDBcbiAgfVxuICB3aGlsZSAob2Zmc2V0IDwgZGF0YS5sZW5ndGgpIGJsb2NrW3RoaXMuX2Jsb2NrT2Zmc2V0KytdID0gZGF0YVtvZmZzZXQrK11cblxuICAvLyB1cGRhdGUgbGVuZ3RoXG4gIGZvciAodmFyIGogPSAwLCBjYXJyeSA9IGRhdGEubGVuZ3RoICogODsgY2FycnkgPiAwOyArK2opIHtcbiAgICB0aGlzLl9sZW5ndGhbal0gKz0gY2FycnlcbiAgICBjYXJyeSA9ICh0aGlzLl9sZW5ndGhbal0gLyAweDAxMDAwMDAwMDApIHwgMFxuICAgIGlmIChjYXJyeSA+IDApIHRoaXMuX2xlbmd0aFtqXSAtPSAweDAxMDAwMDAwMDAgKiBjYXJyeVxuICB9XG5cbiAgcmV0dXJuIHRoaXNcbn1cblxuSGFzaEJhc2UucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gIHRocm93IG5ldyBFcnJvcignX3VwZGF0ZSBpcyBub3QgaW1wbGVtZW50ZWQnKVxufVxuXG5IYXNoQmFzZS5wcm90b3R5cGUuZGlnZXN0ID0gZnVuY3Rpb24gKGVuY29kaW5nKSB7XG4gIGlmICh0aGlzLl9maW5hbGl6ZWQpIHRocm93IG5ldyBFcnJvcignRGlnZXN0IGFscmVhZHkgY2FsbGVkJylcbiAgdGhpcy5fZmluYWxpemVkID0gdHJ1ZVxuXG4gIHZhciBkaWdlc3QgPSB0aGlzLl9kaWdlc3QoKVxuICBpZiAoZW5jb2RpbmcgIT09IHVuZGVmaW5lZCkgZGlnZXN0ID0gZGlnZXN0LnRvU3RyaW5nKGVuY29kaW5nKVxuXG4gIC8vIHJlc2V0IHN0YXRlXG4gIHRoaXMuX2Jsb2NrLmZpbGwoMClcbiAgdGhpcy5fYmxvY2tPZmZzZXQgPSAwXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgNDsgKytpKSB0aGlzLl9sZW5ndGhbaV0gPSAwXG5cbiAgcmV0dXJuIGRpZ2VzdFxufVxuXG5IYXNoQmFzZS5wcm90b3R5cGUuX2RpZ2VzdCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhyb3cgbmV3IEVycm9yKCdfZGlnZXN0IGlzIG5vdCBpbXBsZW1lbnRlZCcpXG59XG5cbm1vZHVsZS5leHBvcnRzID0gSGFzaEJhc2VcbiIsImV4cG9ydHMucmVhZCA9IGZ1bmN0aW9uIChidWZmZXIsIG9mZnNldCwgaXNMRSwgbUxlbiwgbkJ5dGVzKSB7XG4gIHZhciBlLCBtXG4gIHZhciBlTGVuID0gKG5CeXRlcyAqIDgpIC0gbUxlbiAtIDFcbiAgdmFyIGVNYXggPSAoMSA8PCBlTGVuKSAtIDFcbiAgdmFyIGVCaWFzID0gZU1heCA+PiAxXG4gIHZhciBuQml0cyA9IC03XG4gIHZhciBpID0gaXNMRSA/IChuQnl0ZXMgLSAxKSA6IDBcbiAgdmFyIGQgPSBpc0xFID8gLTEgOiAxXG4gIHZhciBzID0gYnVmZmVyW29mZnNldCArIGldXG5cbiAgaSArPSBkXG5cbiAgZSA9IHMgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgcyA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gZUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBlID0gKGUgKiAyNTYpICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgbSA9IGUgJiAoKDEgPDwgKC1uQml0cykpIC0gMSlcbiAgZSA+Pj0gKC1uQml0cylcbiAgbkJpdHMgKz0gbUxlblxuICBmb3IgKDsgbkJpdHMgPiAwOyBtID0gKG0gKiAyNTYpICsgYnVmZmVyW29mZnNldCArIGldLCBpICs9IGQsIG5CaXRzIC09IDgpIHt9XG5cbiAgaWYgKGUgPT09IDApIHtcbiAgICBlID0gMSAtIGVCaWFzXG4gIH0gZWxzZSBpZiAoZSA9PT0gZU1heCkge1xuICAgIHJldHVybiBtID8gTmFOIDogKChzID8gLTEgOiAxKSAqIEluZmluaXR5KVxuICB9IGVsc2Uge1xuICAgIG0gPSBtICsgTWF0aC5wb3coMiwgbUxlbilcbiAgICBlID0gZSAtIGVCaWFzXG4gIH1cbiAgcmV0dXJuIChzID8gLTEgOiAxKSAqIG0gKiBNYXRoLnBvdygyLCBlIC0gbUxlbilcbn1cblxuZXhwb3J0cy53cml0ZSA9IGZ1bmN0aW9uIChidWZmZXIsIHZhbHVlLCBvZmZzZXQsIGlzTEUsIG1MZW4sIG5CeXRlcykge1xuICB2YXIgZSwgbSwgY1xuICB2YXIgZUxlbiA9IChuQnl0ZXMgKiA4KSAtIG1MZW4gLSAxXG4gIHZhciBlTWF4ID0gKDEgPDwgZUxlbikgLSAxXG4gIHZhciBlQmlhcyA9IGVNYXggPj4gMVxuICB2YXIgcnQgPSAobUxlbiA9PT0gMjMgPyBNYXRoLnBvdygyLCAtMjQpIC0gTWF0aC5wb3coMiwgLTc3KSA6IDApXG4gIHZhciBpID0gaXNMRSA/IDAgOiAobkJ5dGVzIC0gMSlcbiAgdmFyIGQgPSBpc0xFID8gMSA6IC0xXG4gIHZhciBzID0gdmFsdWUgPCAwIHx8ICh2YWx1ZSA9PT0gMCAmJiAxIC8gdmFsdWUgPCAwKSA/IDEgOiAwXG5cbiAgdmFsdWUgPSBNYXRoLmFicyh2YWx1ZSlcblxuICBpZiAoaXNOYU4odmFsdWUpIHx8IHZhbHVlID09PSBJbmZpbml0eSkge1xuICAgIG0gPSBpc05hTih2YWx1ZSkgPyAxIDogMFxuICAgIGUgPSBlTWF4XG4gIH0gZWxzZSB7XG4gICAgZSA9IE1hdGguZmxvb3IoTWF0aC5sb2codmFsdWUpIC8gTWF0aC5MTjIpXG4gICAgaWYgKHZhbHVlICogKGMgPSBNYXRoLnBvdygyLCAtZSkpIDwgMSkge1xuICAgICAgZS0tXG4gICAgICBjICo9IDJcbiAgICB9XG4gICAgaWYgKGUgKyBlQmlhcyA+PSAxKSB7XG4gICAgICB2YWx1ZSArPSBydCAvIGNcbiAgICB9IGVsc2Uge1xuICAgICAgdmFsdWUgKz0gcnQgKiBNYXRoLnBvdygyLCAxIC0gZUJpYXMpXG4gICAgfVxuICAgIGlmICh2YWx1ZSAqIGMgPj0gMikge1xuICAgICAgZSsrXG4gICAgICBjIC89IDJcbiAgICB9XG5cbiAgICBpZiAoZSArIGVCaWFzID49IGVNYXgpIHtcbiAgICAgIG0gPSAwXG4gICAgICBlID0gZU1heFxuICAgIH0gZWxzZSBpZiAoZSArIGVCaWFzID49IDEpIHtcbiAgICAgIG0gPSAoKHZhbHVlICogYykgLSAxKSAqIE1hdGgucG93KDIsIG1MZW4pXG4gICAgICBlID0gZSArIGVCaWFzXG4gICAgfSBlbHNlIHtcbiAgICAgIG0gPSB2YWx1ZSAqIE1hdGgucG93KDIsIGVCaWFzIC0gMSkgKiBNYXRoLnBvdygyLCBtTGVuKVxuICAgICAgZSA9IDBcbiAgICB9XG4gIH1cblxuICBmb3IgKDsgbUxlbiA+PSA4OyBidWZmZXJbb2Zmc2V0ICsgaV0gPSBtICYgMHhmZiwgaSArPSBkLCBtIC89IDI1NiwgbUxlbiAtPSA4KSB7fVxuXG4gIGUgPSAoZSA8PCBtTGVuKSB8IG1cbiAgZUxlbiArPSBtTGVuXG4gIGZvciAoOyBlTGVuID4gMDsgYnVmZmVyW29mZnNldCArIGldID0gZSAmIDB4ZmYsIGkgKz0gZCwgZSAvPSAyNTYsIGVMZW4gLT0gOCkge31cblxuICBidWZmZXJbb2Zmc2V0ICsgaSAtIGRdIHw9IHMgKiAxMjhcbn1cbiIsImlmICh0eXBlb2YgT2JqZWN0LmNyZWF0ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAvLyBpbXBsZW1lbnRhdGlvbiBmcm9tIHN0YW5kYXJkIG5vZGUuanMgJ3V0aWwnIG1vZHVsZVxuICBtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIGluaGVyaXRzKGN0b3IsIHN1cGVyQ3Rvcikge1xuICAgIGN0b3Iuc3VwZXJfID0gc3VwZXJDdG9yXG4gICAgY3Rvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ3Rvci5wcm90b3R5cGUsIHtcbiAgICAgIGNvbnN0cnVjdG9yOiB7XG4gICAgICAgIHZhbHVlOiBjdG9yLFxuICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgd3JpdGFibGU6IHRydWUsXG4gICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZVxuICAgICAgfVxuICAgIH0pO1xuICB9O1xufSBlbHNlIHtcbiAgLy8gb2xkIHNjaG9vbCBzaGltIGZvciBvbGQgYnJvd3NlcnNcbiAgbW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpbmhlcml0cyhjdG9yLCBzdXBlckN0b3IpIHtcbiAgICBjdG9yLnN1cGVyXyA9IHN1cGVyQ3RvclxuICAgIHZhciBUZW1wQ3RvciA9IGZ1bmN0aW9uICgpIHt9XG4gICAgVGVtcEN0b3IucHJvdG90eXBlID0gc3VwZXJDdG9yLnByb3RvdHlwZVxuICAgIGN0b3IucHJvdG90eXBlID0gbmV3IFRlbXBDdG9yKClcbiAgICBjdG9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IGN0b3JcbiAgfVxufVxuIiwiLyohXG4gKiBEZXRlcm1pbmUgaWYgYW4gb2JqZWN0IGlzIGEgQnVmZmVyXG4gKlxuICogQGF1dGhvciAgIEZlcm9zcyBBYm91a2hhZGlqZWggPGh0dHBzOi8vZmVyb3NzLm9yZz5cbiAqIEBsaWNlbnNlICBNSVRcbiAqL1xuXG4vLyBUaGUgX2lzQnVmZmVyIGNoZWNrIGlzIGZvciBTYWZhcmkgNS03IHN1cHBvcnQsIGJlY2F1c2UgaXQncyBtaXNzaW5nXG4vLyBPYmplY3QucHJvdG90eXBlLmNvbnN0cnVjdG9yLiBSZW1vdmUgdGhpcyBldmVudHVhbGx5XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChvYmopIHtcbiAgcmV0dXJuIG9iaiAhPSBudWxsICYmIChpc0J1ZmZlcihvYmopIHx8IGlzU2xvd0J1ZmZlcihvYmopIHx8ICEhb2JqLl9pc0J1ZmZlcilcbn1cblxuZnVuY3Rpb24gaXNCdWZmZXIgKG9iaikge1xuICByZXR1cm4gISFvYmouY29uc3RydWN0b3IgJiYgdHlwZW9mIG9iai5jb25zdHJ1Y3Rvci5pc0J1ZmZlciA9PT0gJ2Z1bmN0aW9uJyAmJiBvYmouY29uc3RydWN0b3IuaXNCdWZmZXIob2JqKVxufVxuXG4vLyBGb3IgTm9kZSB2MC4xMCBzdXBwb3J0LiBSZW1vdmUgdGhpcyBldmVudHVhbGx5LlxuZnVuY3Rpb24gaXNTbG93QnVmZmVyIChvYmopIHtcbiAgcmV0dXJuIHR5cGVvZiBvYmoucmVhZEZsb2F0TEUgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIG9iai5zbGljZSA9PT0gJ2Z1bmN0aW9uJyAmJiBpc0J1ZmZlcihvYmouc2xpY2UoMCwgMCkpXG59XG4iLCJ2YXIgdG9TdHJpbmcgPSB7fS50b1N0cmluZztcblxubW9kdWxlLmV4cG9ydHMgPSBBcnJheS5pc0FycmF5IHx8IGZ1bmN0aW9uIChhcnIpIHtcbiAgcmV0dXJuIHRvU3RyaW5nLmNhbGwoYXJyKSA9PSAnW29iamVjdCBBcnJheV0nO1xufTtcbiIsIi8qXHJcbiBDb3B5cmlnaHQgMjAxMyBEYW5pZWwgV2lydHogPGRjb2RlQGRjb2RlLmlvPlxyXG4gQ29weXJpZ2h0IDIwMDkgVGhlIENsb3N1cmUgTGlicmFyeSBBdXRob3JzLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxyXG5cclxuIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSBcIkxpY2Vuc2VcIik7XHJcbiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXHJcbiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcclxuXHJcbiBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjBcclxuXHJcbiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXHJcbiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTLUlTXCIgQkFTSVMsXHJcbiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cclxuIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcclxuIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxyXG4gKi9cclxuXHJcbi8qKlxyXG4gKiBAbGljZW5zZSBsb25nLmpzIChjKSAyMDEzIERhbmllbCBXaXJ0eiA8ZGNvZGVAZGNvZGUuaW8+XHJcbiAqIFJlbGVhc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjBcclxuICogc2VlOiBodHRwczovL2dpdGh1Yi5jb20vZGNvZGVJTy9sb25nLmpzIGZvciBkZXRhaWxzXHJcbiAqL1xyXG4oZnVuY3Rpb24oZ2xvYmFsLCBmYWN0b3J5KSB7XHJcblxyXG4gICAgLyogQU1EICovIGlmICh0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZVtcImFtZFwiXSlcclxuICAgICAgICBkZWZpbmUoW10sIGZhY3RvcnkpO1xyXG4gICAgLyogQ29tbW9uSlMgKi8gZWxzZSBpZiAodHlwZW9mIHJlcXVpcmUgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIG1vZHVsZSA9PT0gXCJvYmplY3RcIiAmJiBtb2R1bGUgJiYgbW9kdWxlW1wiZXhwb3J0c1wiXSlcclxuICAgICAgICBtb2R1bGVbXCJleHBvcnRzXCJdID0gZmFjdG9yeSgpO1xyXG4gICAgLyogR2xvYmFsICovIGVsc2VcclxuICAgICAgICAoZ2xvYmFsW1wiZGNvZGVJT1wiXSA9IGdsb2JhbFtcImRjb2RlSU9cIl0gfHwge30pW1wiTG9uZ1wiXSA9IGZhY3RvcnkoKTtcclxuXHJcbn0pKHRoaXMsIGZ1bmN0aW9uKCkge1xyXG4gICAgXCJ1c2Ugc3RyaWN0XCI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb25zdHJ1Y3RzIGEgNjQgYml0IHR3bydzLWNvbXBsZW1lbnQgaW50ZWdlciwgZ2l2ZW4gaXRzIGxvdyBhbmQgaGlnaCAzMiBiaXQgdmFsdWVzIGFzICpzaWduZWQqIGludGVnZXJzLlxyXG4gICAgICogIFNlZSB0aGUgZnJvbSogZnVuY3Rpb25zIGJlbG93IGZvciBtb3JlIGNvbnZlbmllbnQgd2F5cyBvZiBjb25zdHJ1Y3RpbmcgTG9uZ3MuXHJcbiAgICAgKiBAZXhwb3J0cyBMb25nXHJcbiAgICAgKiBAY2xhc3MgQSBMb25nIGNsYXNzIGZvciByZXByZXNlbnRpbmcgYSA2NCBiaXQgdHdvJ3MtY29tcGxlbWVudCBpbnRlZ2VyIHZhbHVlLlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGxvdyBUaGUgbG93IChzaWduZWQpIDMyIGJpdHMgb2YgdGhlIGxvbmdcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoIFRoZSBoaWdoIChzaWduZWQpIDMyIGJpdHMgb2YgdGhlIGxvbmdcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBgZmFsc2VgIGZvciBzaWduZWRcclxuICAgICAqIEBjb25zdHJ1Y3RvclxyXG4gICAgICovXHJcbiAgICBmdW5jdGlvbiBMb25nKGxvdywgaGlnaCwgdW5zaWduZWQpIHtcclxuXHJcbiAgICAgICAgLyoqXHJcbiAgICAgICAgICogVGhlIGxvdyAzMiBiaXRzIGFzIGEgc2lnbmVkIHZhbHVlLlxyXG4gICAgICAgICAqIEB0eXBlIHtudW1iZXJ9XHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdGhpcy5sb3cgPSBsb3cgfCAwO1xyXG5cclxuICAgICAgICAvKipcclxuICAgICAgICAgKiBUaGUgaGlnaCAzMiBiaXRzIGFzIGEgc2lnbmVkIHZhbHVlLlxyXG4gICAgICAgICAqIEB0eXBlIHtudW1iZXJ9XHJcbiAgICAgICAgICovXHJcbiAgICAgICAgdGhpcy5oaWdoID0gaGlnaCB8IDA7XHJcblxyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LlxyXG4gICAgICAgICAqIEB0eXBlIHtib29sZWFufVxyXG4gICAgICAgICAqL1xyXG4gICAgICAgIHRoaXMudW5zaWduZWQgPSAhIXVuc2lnbmVkO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFRoZSBpbnRlcm5hbCByZXByZXNlbnRhdGlvbiBvZiBhIGxvbmcgaXMgdGhlIHR3byBnaXZlbiBzaWduZWQsIDMyLWJpdCB2YWx1ZXMuXHJcbiAgICAvLyBXZSB1c2UgMzItYml0IHBpZWNlcyBiZWNhdXNlIHRoZXNlIGFyZSB0aGUgc2l6ZSBvZiBpbnRlZ2VycyBvbiB3aGljaFxyXG4gICAgLy8gSmF2YXNjcmlwdCBwZXJmb3JtcyBiaXQtb3BlcmF0aW9ucy4gIEZvciBvcGVyYXRpb25zIGxpa2UgYWRkaXRpb24gYW5kXHJcbiAgICAvLyBtdWx0aXBsaWNhdGlvbiwgd2Ugc3BsaXQgZWFjaCBudW1iZXIgaW50byAxNiBiaXQgcGllY2VzLCB3aGljaCBjYW4gZWFzaWx5IGJlXHJcbiAgICAvLyBtdWx0aXBsaWVkIHdpdGhpbiBKYXZhc2NyaXB0J3MgZmxvYXRpbmctcG9pbnQgcmVwcmVzZW50YXRpb24gd2l0aG91dCBvdmVyZmxvd1xyXG4gICAgLy8gb3IgY2hhbmdlIGluIHNpZ24uXHJcbiAgICAvL1xyXG4gICAgLy8gSW4gdGhlIGFsZ29yaXRobXMgYmVsb3csIHdlIGZyZXF1ZW50bHkgcmVkdWNlIHRoZSBuZWdhdGl2ZSBjYXNlIHRvIHRoZVxyXG4gICAgLy8gcG9zaXRpdmUgY2FzZSBieSBuZWdhdGluZyB0aGUgaW5wdXQocykgYW5kIHRoZW4gcG9zdC1wcm9jZXNzaW5nIHRoZSByZXN1bHQuXHJcbiAgICAvLyBOb3RlIHRoYXQgd2UgbXVzdCBBTFdBWVMgY2hlY2sgc3BlY2lhbGx5IHdoZXRoZXIgdGhvc2UgdmFsdWVzIGFyZSBNSU5fVkFMVUVcclxuICAgIC8vICgtMl42MykgYmVjYXVzZSAtTUlOX1ZBTFVFID09IE1JTl9WQUxVRSAoc2luY2UgMl42MyBjYW5ub3QgYmUgcmVwcmVzZW50ZWQgYXNcclxuICAgIC8vIGEgcG9zaXRpdmUgbnVtYmVyLCBpdCBvdmVyZmxvd3MgYmFjayBpbnRvIGEgbmVnYXRpdmUpLiAgTm90IGhhbmRsaW5nIHRoaXNcclxuICAgIC8vIGNhc2Ugd291bGQgb2Z0ZW4gcmVzdWx0IGluIGluZmluaXRlIHJlY3Vyc2lvbi5cclxuICAgIC8vXHJcbiAgICAvLyBDb21tb24gY29uc3RhbnQgdmFsdWVzIFpFUk8sIE9ORSwgTkVHX09ORSwgZXRjLiBhcmUgZGVmaW5lZCBiZWxvdyB0aGUgZnJvbSpcclxuICAgIC8vIG1ldGhvZHMgb24gd2hpY2ggdGhleSBkZXBlbmQuXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBbiBpbmRpY2F0b3IgdXNlZCB0byByZWxpYWJseSBkZXRlcm1pbmUgaWYgYW4gb2JqZWN0IGlzIGEgTG9uZyBvciBub3QuXHJcbiAgICAgKiBAdHlwZSB7Ym9vbGVhbn1cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQHByaXZhdGVcclxuICAgICAqL1xyXG4gICAgTG9uZy5wcm90b3R5cGUuX19pc0xvbmdfXztcclxuXHJcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoTG9uZy5wcm90b3R5cGUsIFwiX19pc0xvbmdfX1wiLCB7XHJcbiAgICAgICAgdmFsdWU6IHRydWUsXHJcbiAgICAgICAgZW51bWVyYWJsZTogZmFsc2UsXHJcbiAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZVxyXG4gICAgfSk7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7Kn0gb2JqIE9iamVjdFxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgZnVuY3Rpb24gaXNMb25nKG9iaikge1xyXG4gICAgICAgIHJldHVybiAob2JqICYmIG9ialtcIl9faXNMb25nX19cIl0pID09PSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGVzdHMgaWYgdGhlIHNwZWNpZmllZCBvYmplY3QgaXMgYSBMb25nLlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0geyp9IG9iaiBPYmplY3RcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gICAgICovXHJcbiAgICBMb25nLmlzTG9uZyA9IGlzTG9uZztcclxuXHJcbiAgICAvKipcclxuICAgICAqIEEgY2FjaGUgb2YgdGhlIExvbmcgcmVwcmVzZW50YXRpb25zIG9mIHNtYWxsIGludGVnZXIgdmFsdWVzLlxyXG4gICAgICogQHR5cGUgeyFPYmplY3R9XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIElOVF9DQUNIRSA9IHt9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQSBjYWNoZSBvZiB0aGUgTG9uZyByZXByZXNlbnRhdGlvbnMgb2Ygc21hbGwgdW5zaWduZWQgaW50ZWdlciB2YWx1ZXMuXHJcbiAgICAgKiBAdHlwZSB7IU9iamVjdH1cclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICB2YXIgVUlOVF9DQUNIRSA9IHt9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZFxyXG4gICAgICogQHJldHVybnMgeyFMb25nfVxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIGZ1bmN0aW9uIGZyb21JbnQodmFsdWUsIHVuc2lnbmVkKSB7XHJcbiAgICAgICAgdmFyIG9iaiwgY2FjaGVkT2JqLCBjYWNoZTtcclxuICAgICAgICBpZiAodW5zaWduZWQpIHtcclxuICAgICAgICAgICAgdmFsdWUgPj4+PSAwO1xyXG4gICAgICAgICAgICBpZiAoY2FjaGUgPSAoMCA8PSB2YWx1ZSAmJiB2YWx1ZSA8IDI1NikpIHtcclxuICAgICAgICAgICAgICAgIGNhY2hlZE9iaiA9IFVJTlRfQ0FDSEVbdmFsdWVdO1xyXG4gICAgICAgICAgICAgICAgaWYgKGNhY2hlZE9iailcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2FjaGVkT2JqO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIG9iaiA9IGZyb21CaXRzKHZhbHVlLCAodmFsdWUgfCAwKSA8IDAgPyAtMSA6IDAsIHRydWUpO1xyXG4gICAgICAgICAgICBpZiAoY2FjaGUpXHJcbiAgICAgICAgICAgICAgICBVSU5UX0NBQ0hFW3ZhbHVlXSA9IG9iajtcclxuICAgICAgICAgICAgcmV0dXJuIG9iajtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB2YWx1ZSB8PSAwO1xyXG4gICAgICAgICAgICBpZiAoY2FjaGUgPSAoLTEyOCA8PSB2YWx1ZSAmJiB2YWx1ZSA8IDEyOCkpIHtcclxuICAgICAgICAgICAgICAgIGNhY2hlZE9iaiA9IElOVF9DQUNIRVt2YWx1ZV07XHJcbiAgICAgICAgICAgICAgICBpZiAoY2FjaGVkT2JqKVxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjYWNoZWRPYmo7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgb2JqID0gZnJvbUJpdHModmFsdWUsIHZhbHVlIDwgMCA/IC0xIDogMCwgZmFsc2UpO1xyXG4gICAgICAgICAgICBpZiAoY2FjaGUpXHJcbiAgICAgICAgICAgICAgICBJTlRfQ0FDSEVbdmFsdWVdID0gb2JqO1xyXG4gICAgICAgICAgICByZXR1cm4gb2JqO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgYSBMb25nIHJlcHJlc2VudGluZyB0aGUgZ2l2ZW4gMzIgYml0IGludGVnZXIgdmFsdWUuXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZSBUaGUgMzIgYml0IGludGVnZXIgaW4gcXVlc3Rpb25cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBgZmFsc2VgIGZvciBzaWduZWRcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gICAgICovXHJcbiAgICBMb25nLmZyb21JbnQgPSBmcm9tSW50O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXHJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW49fSB1bnNpZ25lZFxyXG4gICAgICogQHJldHVybnMgeyFMb25nfVxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIGZ1bmN0aW9uIGZyb21OdW1iZXIodmFsdWUsIHVuc2lnbmVkKSB7XHJcbiAgICAgICAgaWYgKGlzTmFOKHZhbHVlKSB8fCAhaXNGaW5pdGUodmFsdWUpKVxyXG4gICAgICAgICAgICByZXR1cm4gdW5zaWduZWQgPyBVWkVSTyA6IFpFUk87XHJcbiAgICAgICAgaWYgKHVuc2lnbmVkKSB7XHJcbiAgICAgICAgICAgIGlmICh2YWx1ZSA8IDApXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gVVpFUk87XHJcbiAgICAgICAgICAgIGlmICh2YWx1ZSA+PSBUV09fUFdSXzY0X0RCTClcclxuICAgICAgICAgICAgICAgIHJldHVybiBNQVhfVU5TSUdORURfVkFMVUU7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKHZhbHVlIDw9IC1UV09fUFdSXzYzX0RCTClcclxuICAgICAgICAgICAgICAgIHJldHVybiBNSU5fVkFMVUU7XHJcbiAgICAgICAgICAgIGlmICh2YWx1ZSArIDEgPj0gVFdPX1BXUl82M19EQkwpXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gTUFYX1ZBTFVFO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAodmFsdWUgPCAwKVxyXG4gICAgICAgICAgICByZXR1cm4gZnJvbU51bWJlcigtdmFsdWUsIHVuc2lnbmVkKS5uZWcoKTtcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHMoKHZhbHVlICUgVFdPX1BXUl8zMl9EQkwpIHwgMCwgKHZhbHVlIC8gVFdPX1BXUl8zMl9EQkwpIHwgMCwgdW5zaWduZWQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyBhIExvbmcgcmVwcmVzZW50aW5nIHRoZSBnaXZlbiB2YWx1ZSwgcHJvdmlkZWQgdGhhdCBpdCBpcyBhIGZpbml0ZSBudW1iZXIuIE90aGVyd2lzZSwgemVybyBpcyByZXR1cm5lZC5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlIFRoZSBudW1iZXIgaW4gcXVlc3Rpb25cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBgZmFsc2VgIGZvciBzaWduZWRcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gICAgICovXHJcbiAgICBMb25nLmZyb21OdW1iZXIgPSBmcm9tTnVtYmVyO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGxvd0JpdHNcclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBoaWdoQml0c1xyXG4gICAgICogQHBhcmFtIHtib29sZWFuPX0gdW5zaWduZWRcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ31cclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICBmdW5jdGlvbiBmcm9tQml0cyhsb3dCaXRzLCBoaWdoQml0cywgdW5zaWduZWQpIHtcclxuICAgICAgICByZXR1cm4gbmV3IExvbmcobG93Qml0cywgaGlnaEJpdHMsIHVuc2lnbmVkKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgYSBMb25nIHJlcHJlc2VudGluZyB0aGUgNjQgYml0IGludGVnZXIgdGhhdCBjb21lcyBieSBjb25jYXRlbmF0aW5nIHRoZSBnaXZlbiBsb3cgYW5kIGhpZ2ggYml0cy4gRWFjaCBpc1xyXG4gICAgICogIGFzc3VtZWQgdG8gdXNlIDMyIGJpdHMuXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBsb3dCaXRzIFRoZSBsb3cgMzIgYml0c1xyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGhpZ2hCaXRzIFRoZSBoaWdoIDMyIGJpdHNcclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IHVuc2lnbmVkIFdoZXRoZXIgdW5zaWduZWQgb3Igbm90LCBkZWZhdWx0cyB0byBgZmFsc2VgIGZvciBzaWduZWRcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gICAgICovXHJcbiAgICBMb25nLmZyb21CaXRzID0gZnJvbUJpdHM7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBiYXNlXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gZXhwb25lbnRcclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIHBvd19kYmwgPSBNYXRoLnBvdzsgLy8gVXNlZCA0IHRpbWVzICg0KjggdG8gMTUrNClcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcclxuICAgICAqIEBwYXJhbSB7KGJvb2xlYW58bnVtYmVyKT19IHVuc2lnbmVkXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IHJhZGl4XHJcbiAgICAgKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgZnVuY3Rpb24gZnJvbVN0cmluZyhzdHIsIHVuc2lnbmVkLCByYWRpeCkge1xyXG4gICAgICAgIGlmIChzdHIubGVuZ3RoID09PSAwKVxyXG4gICAgICAgICAgICB0aHJvdyBFcnJvcignZW1wdHkgc3RyaW5nJyk7XHJcbiAgICAgICAgaWYgKHN0ciA9PT0gXCJOYU5cIiB8fCBzdHIgPT09IFwiSW5maW5pdHlcIiB8fCBzdHIgPT09IFwiK0luZmluaXR5XCIgfHwgc3RyID09PSBcIi1JbmZpbml0eVwiKVxyXG4gICAgICAgICAgICByZXR1cm4gWkVSTztcclxuICAgICAgICBpZiAodHlwZW9mIHVuc2lnbmVkID09PSAnbnVtYmVyJykge1xyXG4gICAgICAgICAgICAvLyBGb3IgZ29vZy5tYXRoLmxvbmcgY29tcGF0aWJpbGl0eVxyXG4gICAgICAgICAgICByYWRpeCA9IHVuc2lnbmVkLFxyXG4gICAgICAgICAgICB1bnNpZ25lZCA9IGZhbHNlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHVuc2lnbmVkID0gISEgdW5zaWduZWQ7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJhZGl4ID0gcmFkaXggfHwgMTA7XHJcbiAgICAgICAgaWYgKHJhZGl4IDwgMiB8fCAzNiA8IHJhZGl4KVxyXG4gICAgICAgICAgICB0aHJvdyBSYW5nZUVycm9yKCdyYWRpeCcpO1xyXG5cclxuICAgICAgICB2YXIgcDtcclxuICAgICAgICBpZiAoKHAgPSBzdHIuaW5kZXhPZignLScpKSA+IDApXHJcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdpbnRlcmlvciBoeXBoZW4nKTtcclxuICAgICAgICBlbHNlIGlmIChwID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmcm9tU3RyaW5nKHN0ci5zdWJzdHJpbmcoMSksIHVuc2lnbmVkLCByYWRpeCkubmVnKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBEbyBzZXZlcmFsICg4KSBkaWdpdHMgZWFjaCB0aW1lIHRocm91Z2ggdGhlIGxvb3AsIHNvIGFzIHRvXHJcbiAgICAgICAgLy8gbWluaW1pemUgdGhlIGNhbGxzIHRvIHRoZSB2ZXJ5IGV4cGVuc2l2ZSBlbXVsYXRlZCBkaXYuXHJcbiAgICAgICAgdmFyIHJhZGl4VG9Qb3dlciA9IGZyb21OdW1iZXIocG93X2RibChyYWRpeCwgOCkpO1xyXG5cclxuICAgICAgICB2YXIgcmVzdWx0ID0gWkVSTztcclxuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IHN0ci5sZW5ndGg7IGkgKz0gOCkge1xyXG4gICAgICAgICAgICB2YXIgc2l6ZSA9IE1hdGgubWluKDgsIHN0ci5sZW5ndGggLSBpKSxcclxuICAgICAgICAgICAgICAgIHZhbHVlID0gcGFyc2VJbnQoc3RyLnN1YnN0cmluZyhpLCBpICsgc2l6ZSksIHJhZGl4KTtcclxuICAgICAgICAgICAgaWYgKHNpemUgPCA4KSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgcG93ZXIgPSBmcm9tTnVtYmVyKHBvd19kYmwocmFkaXgsIHNpemUpKTtcclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5tdWwocG93ZXIpLmFkZChmcm9tTnVtYmVyKHZhbHVlKSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQubXVsKHJhZGl4VG9Qb3dlcik7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQgPSByZXN1bHQuYWRkKGZyb21OdW1iZXIodmFsdWUpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICByZXN1bHQudW5zaWduZWQgPSB1bnNpZ25lZDtcclxuICAgICAgICByZXR1cm4gcmVzdWx0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyBhIExvbmcgcmVwcmVzZW50YXRpb24gb2YgdGhlIGdpdmVuIHN0cmluZywgd3JpdHRlbiB1c2luZyB0aGUgc3BlY2lmaWVkIHJhZGl4LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc3RyIFRoZSB0ZXh0dWFsIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBMb25nXHJcbiAgICAgKiBAcGFyYW0geyhib29sZWFufG51bWJlcik9fSB1bnNpZ25lZCBXaGV0aGVyIHVuc2lnbmVkIG9yIG5vdCwgZGVmYXVsdHMgdG8gYGZhbHNlYCBmb3Igc2lnbmVkXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcj19IHJhZGl4IFRoZSByYWRpeCBpbiB3aGljaCB0aGUgdGV4dCBpcyB3cml0dGVuICgyLTM2KSwgZGVmYXVsdHMgdG8gMTBcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gVGhlIGNvcnJlc3BvbmRpbmcgTG9uZyB2YWx1ZVxyXG4gICAgICovXHJcbiAgICBMb25nLmZyb21TdHJpbmcgPSBmcm9tU3RyaW5nO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd8IXtsb3c6IG51bWJlciwgaGlnaDogbnVtYmVyLCB1bnNpZ25lZDogYm9vbGVhbn19IHZhbFxyXG4gICAgICogQHJldHVybnMgeyFMb25nfVxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIGZ1bmN0aW9uIGZyb21WYWx1ZSh2YWwpIHtcclxuICAgICAgICBpZiAodmFsIC8qIGlzIGNvbXBhdGlibGUgKi8gaW5zdGFuY2VvZiBMb25nKVxyXG4gICAgICAgICAgICByZXR1cm4gdmFsO1xyXG4gICAgICAgIGlmICh0eXBlb2YgdmFsID09PSAnbnVtYmVyJylcclxuICAgICAgICAgICAgcmV0dXJuIGZyb21OdW1iZXIodmFsKTtcclxuICAgICAgICBpZiAodHlwZW9mIHZhbCA9PT0gJ3N0cmluZycpXHJcbiAgICAgICAgICAgIHJldHVybiBmcm9tU3RyaW5nKHZhbCk7XHJcbiAgICAgICAgLy8gVGhyb3dzIGZvciBub24tb2JqZWN0cywgY29udmVydHMgbm9uLWluc3RhbmNlb2YgTG9uZzpcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHModmFsLmxvdywgdmFsLmhpZ2gsIHZhbC51bnNpZ25lZCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb252ZXJ0cyB0aGUgc3BlY2lmaWVkIHZhbHVlIHRvIGEgTG9uZy5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfCF7bG93OiBudW1iZXIsIGhpZ2g6IG51bWJlciwgdW5zaWduZWQ6IGJvb2xlYW59fSB2YWwgVmFsdWVcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ31cclxuICAgICAqL1xyXG4gICAgTG9uZy5mcm9tVmFsdWUgPSBmcm9tVmFsdWU7XHJcblxyXG4gICAgLy8gTk9URTogdGhlIGNvbXBpbGVyIHNob3VsZCBpbmxpbmUgdGhlc2UgY29uc3RhbnQgdmFsdWVzIGJlbG93IGFuZCB0aGVuIHJlbW92ZSB0aGVzZSB2YXJpYWJsZXMsIHNvIHRoZXJlIHNob3VsZCBiZVxyXG4gICAgLy8gbm8gcnVudGltZSBwZW5hbHR5IGZvciB0aGVzZS5cclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHtudW1iZXJ9XHJcbiAgICAgKiBAY29uc3RcclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICB2YXIgVFdPX1BXUl8xNl9EQkwgPSAxIDw8IDE2O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUge251bWJlcn1cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIHZhciBUV09fUFdSXzI0X0RCTCA9IDEgPDwgMjQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7bnVtYmVyfVxyXG4gICAgICogQGNvbnN0XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIFRXT19QV1JfMzJfREJMID0gVFdPX1BXUl8xNl9EQkwgKiBUV09fUFdSXzE2X0RCTDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHtudW1iZXJ9XHJcbiAgICAgKiBAY29uc3RcclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICB2YXIgVFdPX1BXUl82NF9EQkwgPSBUV09fUFdSXzMyX0RCTCAqIFRXT19QV1JfMzJfREJMO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUge251bWJlcn1cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIHZhciBUV09fUFdSXzYzX0RCTCA9IFRXT19QV1JfNjRfREJMIC8gMjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHshTG9uZ31cclxuICAgICAqIEBjb25zdFxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIHZhciBUV09fUFdSXzI0ID0gZnJvbUludChUV09fUFdSXzI0X0RCTCk7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7IUxvbmd9XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIFpFUk8gPSBmcm9tSW50KDApO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2lnbmVkIHplcm8uXHJcbiAgICAgKiBAdHlwZSB7IUxvbmd9XHJcbiAgICAgKi9cclxuICAgIExvbmcuWkVSTyA9IFpFUk87XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7IUxvbmd9XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIFVaRVJPID0gZnJvbUludCgwLCB0cnVlKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFVuc2lnbmVkIHplcm8uXHJcbiAgICAgKiBAdHlwZSB7IUxvbmd9XHJcbiAgICAgKi9cclxuICAgIExvbmcuVVpFUk8gPSBVWkVSTztcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHshTG9uZ31cclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICB2YXIgT05FID0gZnJvbUludCgxKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFNpZ25lZCBvbmUuXHJcbiAgICAgKiBAdHlwZSB7IUxvbmd9XHJcbiAgICAgKi9cclxuICAgIExvbmcuT05FID0gT05FO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQHR5cGUgeyFMb25nfVxyXG4gICAgICogQGlubmVyXHJcbiAgICAgKi9cclxuICAgIHZhciBVT05FID0gZnJvbUludCgxLCB0cnVlKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFVuc2lnbmVkIG9uZS5cclxuICAgICAqIEB0eXBlIHshTG9uZ31cclxuICAgICAqL1xyXG4gICAgTG9uZy5VT05FID0gVU9ORTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHshTG9uZ31cclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICB2YXIgTkVHX09ORSA9IGZyb21JbnQoLTEpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2lnbmVkIG5lZ2F0aXZlIG9uZS5cclxuICAgICAqIEB0eXBlIHshTG9uZ31cclxuICAgICAqL1xyXG4gICAgTG9uZy5ORUdfT05FID0gTkVHX09ORTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHshTG9uZ31cclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICB2YXIgTUFYX1ZBTFVFID0gZnJvbUJpdHMoMHhGRkZGRkZGRnwwLCAweDdGRkZGRkZGfDAsIGZhbHNlKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIE1heGltdW0gc2lnbmVkIHZhbHVlLlxyXG4gICAgICogQHR5cGUgeyFMb25nfVxyXG4gICAgICovXHJcbiAgICBMb25nLk1BWF9WQUxVRSA9IE1BWF9WQUxVRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEB0eXBlIHshTG9uZ31cclxuICAgICAqIEBpbm5lclxyXG4gICAgICovXHJcbiAgICB2YXIgTUFYX1VOU0lHTkVEX1ZBTFVFID0gZnJvbUJpdHMoMHhGRkZGRkZGRnwwLCAweEZGRkZGRkZGfDAsIHRydWUpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWF4aW11bSB1bnNpZ25lZCB2YWx1ZS5cclxuICAgICAqIEB0eXBlIHshTG9uZ31cclxuICAgICAqL1xyXG4gICAgTG9uZy5NQVhfVU5TSUdORURfVkFMVUUgPSBNQVhfVU5TSUdORURfVkFMVUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAdHlwZSB7IUxvbmd9XHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIE1JTl9WQUxVRSA9IGZyb21CaXRzKDAsIDB4ODAwMDAwMDB8MCwgZmFsc2UpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogTWluaW11bSBzaWduZWQgdmFsdWUuXHJcbiAgICAgKiBAdHlwZSB7IUxvbmd9XHJcbiAgICAgKi9cclxuICAgIExvbmcuTUlOX1ZBTFVFID0gTUlOX1ZBTFVFO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGFsaWFzIExvbmcucHJvdG90eXBlXHJcbiAgICAgKiBAaW5uZXJcclxuICAgICAqL1xyXG4gICAgdmFyIExvbmdQcm90b3R5cGUgPSBMb25nLnByb3RvdHlwZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnZlcnRzIHRoZSBMb25nIHRvIGEgMzIgYml0IGludGVnZXIsIGFzc3VtaW5nIGl0IGlzIGEgMzIgYml0IGludGVnZXIuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLnRvSW50ID0gZnVuY3Rpb24gdG9JbnQoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMudW5zaWduZWQgPyB0aGlzLmxvdyA+Pj4gMCA6IHRoaXMubG93O1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnZlcnRzIHRoZSBMb25nIHRvIGEgdGhlIG5lYXJlc3QgZmxvYXRpbmctcG9pbnQgcmVwcmVzZW50YXRpb24gb2YgdGhpcyB2YWx1ZSAoZG91YmxlLCA1MyBiaXQgbWFudGlzc2EpLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn1cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS50b051bWJlciA9IGZ1bmN0aW9uIHRvTnVtYmVyKCkge1xyXG4gICAgICAgIGlmICh0aGlzLnVuc2lnbmVkKVxyXG4gICAgICAgICAgICByZXR1cm4gKCh0aGlzLmhpZ2ggPj4+IDApICogVFdPX1BXUl8zMl9EQkwpICsgKHRoaXMubG93ID4+PiAwKTtcclxuICAgICAgICByZXR1cm4gdGhpcy5oaWdoICogVFdPX1BXUl8zMl9EQkwgKyAodGhpcy5sb3cgPj4+IDApO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnZlcnRzIHRoZSBMb25nIHRvIGEgc3RyaW5nIHdyaXR0ZW4gaW4gdGhlIHNwZWNpZmllZCByYWRpeC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyPX0gcmFkaXggUmFkaXggKDItMzYpLCBkZWZhdWx0cyB0byAxMFxyXG4gICAgICogQHJldHVybnMge3N0cmluZ31cclxuICAgICAqIEBvdmVycmlkZVxyXG4gICAgICogQHRocm93cyB7UmFuZ2VFcnJvcn0gSWYgYHJhZGl4YCBpcyBvdXQgb2YgcmFuZ2VcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS50b1N0cmluZyA9IGZ1bmN0aW9uIHRvU3RyaW5nKHJhZGl4KSB7XHJcbiAgICAgICAgcmFkaXggPSByYWRpeCB8fCAxMDtcclxuICAgICAgICBpZiAocmFkaXggPCAyIHx8IDM2IDwgcmFkaXgpXHJcbiAgICAgICAgICAgIHRocm93IFJhbmdlRXJyb3IoJ3JhZGl4Jyk7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNaZXJvKCkpXHJcbiAgICAgICAgICAgIHJldHVybiAnMCc7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNOZWdhdGl2ZSgpKSB7IC8vIFVuc2lnbmVkIExvbmdzIGFyZSBuZXZlciBuZWdhdGl2ZVxyXG4gICAgICAgICAgICBpZiAodGhpcy5lcShNSU5fVkFMVUUpKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIGNoYW5nZSB0aGUgTG9uZyB2YWx1ZSBiZWZvcmUgaXQgY2FuIGJlIG5lZ2F0ZWQsIHNvIHdlIHJlbW92ZVxyXG4gICAgICAgICAgICAgICAgLy8gdGhlIGJvdHRvbS1tb3N0IGRpZ2l0IGluIHRoaXMgYmFzZSBhbmQgdGhlbiByZWN1cnNlIHRvIGRvIHRoZSByZXN0LlxyXG4gICAgICAgICAgICAgICAgdmFyIHJhZGl4TG9uZyA9IGZyb21OdW1iZXIocmFkaXgpLFxyXG4gICAgICAgICAgICAgICAgICAgIGRpdiA9IHRoaXMuZGl2KHJhZGl4TG9uZyksXHJcbiAgICAgICAgICAgICAgICAgICAgcmVtMSA9IGRpdi5tdWwocmFkaXhMb25nKS5zdWIodGhpcyk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZGl2LnRvU3RyaW5nKHJhZGl4KSArIHJlbTEudG9JbnQoKS50b1N0cmluZyhyYWRpeCk7XHJcbiAgICAgICAgICAgIH0gZWxzZVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuICctJyArIHRoaXMubmVnKCkudG9TdHJpbmcocmFkaXgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gRG8gc2V2ZXJhbCAoNikgZGlnaXRzIGVhY2ggdGltZSB0aHJvdWdoIHRoZSBsb29wLCBzbyBhcyB0b1xyXG4gICAgICAgIC8vIG1pbmltaXplIHRoZSBjYWxscyB0byB0aGUgdmVyeSBleHBlbnNpdmUgZW11bGF0ZWQgZGl2LlxyXG4gICAgICAgIHZhciByYWRpeFRvUG93ZXIgPSBmcm9tTnVtYmVyKHBvd19kYmwocmFkaXgsIDYpLCB0aGlzLnVuc2lnbmVkKSxcclxuICAgICAgICAgICAgcmVtID0gdGhpcztcclxuICAgICAgICB2YXIgcmVzdWx0ID0gJyc7XHJcbiAgICAgICAgd2hpbGUgKHRydWUpIHtcclxuICAgICAgICAgICAgdmFyIHJlbURpdiA9IHJlbS5kaXYocmFkaXhUb1Bvd2VyKSxcclxuICAgICAgICAgICAgICAgIGludHZhbCA9IHJlbS5zdWIocmVtRGl2Lm11bChyYWRpeFRvUG93ZXIpKS50b0ludCgpID4+PiAwLFxyXG4gICAgICAgICAgICAgICAgZGlnaXRzID0gaW50dmFsLnRvU3RyaW5nKHJhZGl4KTtcclxuICAgICAgICAgICAgcmVtID0gcmVtRGl2O1xyXG4gICAgICAgICAgICBpZiAocmVtLmlzWmVybygpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGRpZ2l0cyArIHJlc3VsdDtcclxuICAgICAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB3aGlsZSAoZGlnaXRzLmxlbmd0aCA8IDYpXHJcbiAgICAgICAgICAgICAgICAgICAgZGlnaXRzID0gJzAnICsgZGlnaXRzO1xyXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gJycgKyBkaWdpdHMgKyByZXN1bHQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgaGlnaCAzMiBiaXRzIGFzIGEgc2lnbmVkIGludGVnZXIuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBTaWduZWQgaGlnaCBiaXRzXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuZ2V0SGlnaEJpdHMgPSBmdW5jdGlvbiBnZXRIaWdoQml0cygpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5oaWdoO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgdGhlIGhpZ2ggMzIgYml0cyBhcyBhbiB1bnNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn0gVW5zaWduZWQgaGlnaCBiaXRzXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuZ2V0SGlnaEJpdHNVbnNpZ25lZCA9IGZ1bmN0aW9uIGdldEhpZ2hCaXRzVW5zaWduZWQoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaGlnaCA+Pj4gMDtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBsb3cgMzIgYml0cyBhcyBhIHNpZ25lZCBpbnRlZ2VyLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn0gU2lnbmVkIGxvdyBiaXRzXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuZ2V0TG93Qml0cyA9IGZ1bmN0aW9uIGdldExvd0JpdHMoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMubG93O1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgdGhlIGxvdyAzMiBiaXRzIGFzIGFuIHVuc2lnbmVkIGludGVnZXIuXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSBVbnNpZ25lZCBsb3cgYml0c1xyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLmdldExvd0JpdHNVbnNpZ25lZCA9IGZ1bmN0aW9uIGdldExvd0JpdHNVbnNpZ25lZCgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5sb3cgPj4+IDA7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgbnVtYmVyIG9mIGJpdHMgbmVlZGVkIHRvIHJlcHJlc2VudCB0aGUgYWJzb2x1dGUgdmFsdWUgb2YgdGhpcyBMb25nLlxyXG4gICAgICogQHJldHVybnMge251bWJlcn1cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5nZXROdW1CaXRzQWJzID0gZnVuY3Rpb24gZ2V0TnVtQml0c0FicygpIHtcclxuICAgICAgICBpZiAodGhpcy5pc05lZ2F0aXZlKCkpIC8vIFVuc2lnbmVkIExvbmdzIGFyZSBuZXZlciBuZWdhdGl2ZVxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lcShNSU5fVkFMVUUpID8gNjQgOiB0aGlzLm5lZygpLmdldE51bUJpdHNBYnMoKTtcclxuICAgICAgICB2YXIgdmFsID0gdGhpcy5oaWdoICE9IDAgPyB0aGlzLmhpZ2ggOiB0aGlzLmxvdztcclxuICAgICAgICBmb3IgKHZhciBiaXQgPSAzMTsgYml0ID4gMDsgYml0LS0pXHJcbiAgICAgICAgICAgIGlmICgodmFsICYgKDEgPDwgYml0KSkgIT0gMClcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgIHJldHVybiB0aGlzLmhpZ2ggIT0gMCA/IGJpdCArIDMzIDogYml0ICsgMTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBlcXVhbHMgemVyby5cclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLmlzWmVybyA9IGZ1bmN0aW9uIGlzWmVybygpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5oaWdoID09PSAwICYmIHRoaXMubG93ID09PSAwO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIG5lZ2F0aXZlLlxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuaXNOZWdhdGl2ZSA9IGZ1bmN0aW9uIGlzTmVnYXRpdmUoKSB7XHJcbiAgICAgICAgcmV0dXJuICF0aGlzLnVuc2lnbmVkICYmIHRoaXMuaGlnaCA8IDA7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgcG9zaXRpdmUuXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5pc1Bvc2l0aXZlID0gZnVuY3Rpb24gaXNQb3NpdGl2ZSgpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy51bnNpZ25lZCB8fCB0aGlzLmhpZ2ggPj0gMDtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBvZGQuXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5pc09kZCA9IGZ1bmN0aW9uIGlzT2RkKCkge1xyXG4gICAgICAgIHJldHVybiAodGhpcy5sb3cgJiAxKSA9PT0gMTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBldmVuLlxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuaXNFdmVuID0gZnVuY3Rpb24gaXNFdmVuKCkge1xyXG4gICAgICAgIHJldHVybiAodGhpcy5sb3cgJiAxKSA9PT0gMDtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBlcXVhbHMgdGhlIHNwZWNpZmllZCdzLlxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuZXF1YWxzID0gZnVuY3Rpb24gZXF1YWxzKG90aGVyKSB7XHJcbiAgICAgICAgaWYgKCFpc0xvbmcob3RoZXIpKVxyXG4gICAgICAgICAgICBvdGhlciA9IGZyb21WYWx1ZShvdGhlcik7XHJcbiAgICAgICAgaWYgKHRoaXMudW5zaWduZWQgIT09IG90aGVyLnVuc2lnbmVkICYmICh0aGlzLmhpZ2ggPj4+IDMxKSA9PT0gMSAmJiAob3RoZXIuaGlnaCA+Pj4gMzEpID09PSAxKVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaGlnaCA9PT0gb3RoZXIuaGlnaCAmJiB0aGlzLmxvdyA9PT0gb3RoZXIubG93O1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGVxdWFscyB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjZXF1YWxzfS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuZXEgPSBMb25nUHJvdG90eXBlLmVxdWFscztcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGRpZmZlcnMgZnJvbSB0aGUgc3BlY2lmaWVkJ3MuXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5ub3RFcXVhbHMgPSBmdW5jdGlvbiBub3RFcXVhbHMob3RoZXIpIHtcclxuICAgICAgICByZXR1cm4gIXRoaXMuZXEoLyogdmFsaWRhdGVzICovIG90aGVyKTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBkaWZmZXJzIGZyb20gdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI25vdEVxdWFsc30uXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLm5lcSA9IExvbmdQcm90b3R5cGUubm90RXF1YWxzO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgbGVzcyB0aGFuIHRoZSBzcGVjaWZpZWQncy5cclxuICAgICAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLmxlc3NUaGFuID0gZnVuY3Rpb24gbGVzc1RoYW4ob3RoZXIpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5jb21wKC8qIHZhbGlkYXRlcyAqLyBvdGhlcikgPCAwO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGxlc3MgdGhhbiB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbGVzc1RoYW59LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5sdCA9IExvbmdQcm90b3R5cGUubGVzc1RoYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdGhlIHNwZWNpZmllZCdzLlxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUubGVzc1RoYW5PckVxdWFsID0gZnVuY3Rpb24gbGVzc1RoYW5PckVxdWFsKG90aGVyKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcCgvKiB2YWxpZGF0ZXMgKi8gb3RoZXIpIDw9IDA7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgbGVzcyB0aGFuIG9yIGVxdWFsIHRoZSBzcGVjaWZpZWQncy4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNsZXNzVGhhbk9yRXF1YWx9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5sdGUgPSBMb25nUHJvdG90eXBlLmxlc3NUaGFuT3JFcXVhbDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGdyZWF0ZXIgdGhhbiB0aGUgc3BlY2lmaWVkJ3MuXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5ncmVhdGVyVGhhbiA9IGZ1bmN0aW9uIGdyZWF0ZXJUaGFuKG90aGVyKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcCgvKiB2YWxpZGF0ZXMgKi8gb3RoZXIpID4gMDtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUZXN0cyBpZiB0aGlzIExvbmcncyB2YWx1ZSBpcyBncmVhdGVyIHRoYW4gdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2dyZWF0ZXJUaGFufS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuZ3QgPSBMb25nUHJvdG90eXBlLmdyZWF0ZXJUaGFuO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGVzdHMgaWYgdGhpcyBMb25nJ3MgdmFsdWUgaXMgZ3JlYXRlciB0aGFuIG9yIGVxdWFsIHRoZSBzcGVjaWZpZWQncy5cclxuICAgICAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLmdyZWF0ZXJUaGFuT3JFcXVhbCA9IGZ1bmN0aW9uIGdyZWF0ZXJUaGFuT3JFcXVhbChvdGhlcikge1xyXG4gICAgICAgIHJldHVybiB0aGlzLmNvbXAoLyogdmFsaWRhdGVzICovIG90aGVyKSA+PSAwO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRlc3RzIGlmIHRoaXMgTG9uZydzIHZhbHVlIGlzIGdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0aGUgc3BlY2lmaWVkJ3MuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjZ3JlYXRlclRoYW5PckVxdWFsfS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciB2YWx1ZVxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuZ3RlID0gTG9uZ1Byb3RvdHlwZS5ncmVhdGVyVGhhbk9yRXF1YWw7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb21wYXJlcyB0aGlzIExvbmcncyB2YWx1ZSB3aXRoIHRoZSBzcGVjaWZpZWQncy5cclxuICAgICAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gb3RoZXIgT3RoZXIgdmFsdWVcclxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9IDAgaWYgdGhleSBhcmUgdGhlIHNhbWUsIDEgaWYgdGhlIHRoaXMgaXMgZ3JlYXRlciBhbmQgLTFcclxuICAgICAqICBpZiB0aGUgZ2l2ZW4gb25lIGlzIGdyZWF0ZXJcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5jb21wYXJlID0gZnVuY3Rpb24gY29tcGFyZShvdGhlcikge1xyXG4gICAgICAgIGlmICghaXNMb25nKG90aGVyKSlcclxuICAgICAgICAgICAgb3RoZXIgPSBmcm9tVmFsdWUob3RoZXIpO1xyXG4gICAgICAgIGlmICh0aGlzLmVxKG90aGVyKSlcclxuICAgICAgICAgICAgcmV0dXJuIDA7XHJcbiAgICAgICAgdmFyIHRoaXNOZWcgPSB0aGlzLmlzTmVnYXRpdmUoKSxcclxuICAgICAgICAgICAgb3RoZXJOZWcgPSBvdGhlci5pc05lZ2F0aXZlKCk7XHJcbiAgICAgICAgaWYgKHRoaXNOZWcgJiYgIW90aGVyTmVnKVxyXG4gICAgICAgICAgICByZXR1cm4gLTE7XHJcbiAgICAgICAgaWYgKCF0aGlzTmVnICYmIG90aGVyTmVnKVxyXG4gICAgICAgICAgICByZXR1cm4gMTtcclxuICAgICAgICAvLyBBdCB0aGlzIHBvaW50IHRoZSBzaWduIGJpdHMgYXJlIHRoZSBzYW1lXHJcbiAgICAgICAgaWYgKCF0aGlzLnVuc2lnbmVkKVxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5zdWIob3RoZXIpLmlzTmVnYXRpdmUoKSA/IC0xIDogMTtcclxuICAgICAgICAvLyBCb3RoIGFyZSBwb3NpdGl2ZSBpZiBhdCBsZWFzdCBvbmUgaXMgdW5zaWduZWRcclxuICAgICAgICByZXR1cm4gKG90aGVyLmhpZ2ggPj4+IDApID4gKHRoaXMuaGlnaCA+Pj4gMCkgfHwgKG90aGVyLmhpZ2ggPT09IHRoaXMuaGlnaCAmJiAob3RoZXIubG93ID4+PiAwKSA+ICh0aGlzLmxvdyA+Pj4gMCkpID8gLTEgOiAxO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbXBhcmVzIHRoaXMgTG9uZydzIHZhbHVlIHdpdGggdGhlIHNwZWNpZmllZCdzLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI2NvbXBhcmV9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIHZhbHVlXHJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfSAwIGlmIHRoZXkgYXJlIHRoZSBzYW1lLCAxIGlmIHRoZSB0aGlzIGlzIGdyZWF0ZXIgYW5kIC0xXHJcbiAgICAgKiAgaWYgdGhlIGdpdmVuIG9uZSBpcyBncmVhdGVyXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuY29tcCA9IExvbmdQcm90b3R5cGUuY29tcGFyZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIE5lZ2F0ZXMgdGhpcyBMb25nJ3MgdmFsdWUuXHJcbiAgICAgKiBAcmV0dXJucyB7IUxvbmd9IE5lZ2F0ZWQgTG9uZ1xyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLm5lZ2F0ZSA9IGZ1bmN0aW9uIG5lZ2F0ZSgpIHtcclxuICAgICAgICBpZiAoIXRoaXMudW5zaWduZWQgJiYgdGhpcy5lcShNSU5fVkFMVUUpKVxyXG4gICAgICAgICAgICByZXR1cm4gTUlOX1ZBTFVFO1xyXG4gICAgICAgIHJldHVybiB0aGlzLm5vdCgpLmFkZChPTkUpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIE5lZ2F0ZXMgdGhpcyBMb25nJ3MgdmFsdWUuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjbmVnYXRlfS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHJldHVybnMgeyFMb25nfSBOZWdhdGVkIExvbmdcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5uZWcgPSBMb25nUHJvdG90eXBlLm5lZ2F0ZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhlIHN1bSBvZiB0aGlzIGFuZCB0aGUgc3BlY2lmaWVkIExvbmcuXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IGFkZGVuZCBBZGRlbmRcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gU3VtXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuYWRkID0gZnVuY3Rpb24gYWRkKGFkZGVuZCkge1xyXG4gICAgICAgIGlmICghaXNMb25nKGFkZGVuZCkpXHJcbiAgICAgICAgICAgIGFkZGVuZCA9IGZyb21WYWx1ZShhZGRlbmQpO1xyXG5cclxuICAgICAgICAvLyBEaXZpZGUgZWFjaCBudW1iZXIgaW50byA0IGNodW5rcyBvZiAxNiBiaXRzLCBhbmQgdGhlbiBzdW0gdGhlIGNodW5rcy5cclxuXHJcbiAgICAgICAgdmFyIGE0OCA9IHRoaXMuaGlnaCA+Pj4gMTY7XHJcbiAgICAgICAgdmFyIGEzMiA9IHRoaXMuaGlnaCAmIDB4RkZGRjtcclxuICAgICAgICB2YXIgYTE2ID0gdGhpcy5sb3cgPj4+IDE2O1xyXG4gICAgICAgIHZhciBhMDAgPSB0aGlzLmxvdyAmIDB4RkZGRjtcclxuXHJcbiAgICAgICAgdmFyIGI0OCA9IGFkZGVuZC5oaWdoID4+PiAxNjtcclxuICAgICAgICB2YXIgYjMyID0gYWRkZW5kLmhpZ2ggJiAweEZGRkY7XHJcbiAgICAgICAgdmFyIGIxNiA9IGFkZGVuZC5sb3cgPj4+IDE2O1xyXG4gICAgICAgIHZhciBiMDAgPSBhZGRlbmQubG93ICYgMHhGRkZGO1xyXG5cclxuICAgICAgICB2YXIgYzQ4ID0gMCwgYzMyID0gMCwgYzE2ID0gMCwgYzAwID0gMDtcclxuICAgICAgICBjMDAgKz0gYTAwICsgYjAwO1xyXG4gICAgICAgIGMxNiArPSBjMDAgPj4+IDE2O1xyXG4gICAgICAgIGMwMCAmPSAweEZGRkY7XHJcbiAgICAgICAgYzE2ICs9IGExNiArIGIxNjtcclxuICAgICAgICBjMzIgKz0gYzE2ID4+PiAxNjtcclxuICAgICAgICBjMTYgJj0gMHhGRkZGO1xyXG4gICAgICAgIGMzMiArPSBhMzIgKyBiMzI7XHJcbiAgICAgICAgYzQ4ICs9IGMzMiA+Pj4gMTY7XHJcbiAgICAgICAgYzMyICY9IDB4RkZGRjtcclxuICAgICAgICBjNDggKz0gYTQ4ICsgYjQ4O1xyXG4gICAgICAgIGM0OCAmPSAweEZGRkY7XHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKChjMTYgPDwgMTYpIHwgYzAwLCAoYzQ4IDw8IDE2KSB8IGMzMiwgdGhpcy51bnNpZ25lZCk7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgZGlmZmVyZW5jZSBvZiB0aGlzIGFuZCB0aGUgc3BlY2lmaWVkIExvbmcuXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IHN1YnRyYWhlbmQgU3VidHJhaGVuZFxyXG4gICAgICogQHJldHVybnMgeyFMb25nfSBEaWZmZXJlbmNlXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuc3VidHJhY3QgPSBmdW5jdGlvbiBzdWJ0cmFjdChzdWJ0cmFoZW5kKSB7XHJcbiAgICAgICAgaWYgKCFpc0xvbmcoc3VidHJhaGVuZCkpXHJcbiAgICAgICAgICAgIHN1YnRyYWhlbmQgPSBmcm9tVmFsdWUoc3VidHJhaGVuZCk7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuYWRkKHN1YnRyYWhlbmQubmVnKCkpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhlIGRpZmZlcmVuY2Ugb2YgdGhpcyBhbmQgdGhlIHNwZWNpZmllZCBMb25nLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI3N1YnRyYWN0fS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBzdWJ0cmFoZW5kIFN1YnRyYWhlbmRcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gRGlmZmVyZW5jZVxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLnN1YiA9IExvbmdQcm90b3R5cGUuc3VidHJhY3Q7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoZSBwcm9kdWN0IG9mIHRoaXMgYW5kIHRoZSBzcGVjaWZpZWQgTG9uZy5cclxuICAgICAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gbXVsdGlwbGllciBNdWx0aXBsaWVyXHJcbiAgICAgKiBAcmV0dXJucyB7IUxvbmd9IFByb2R1Y3RcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5tdWx0aXBseSA9IGZ1bmN0aW9uIG11bHRpcGx5KG11bHRpcGxpZXIpIHtcclxuICAgICAgICBpZiAodGhpcy5pc1plcm8oKSlcclxuICAgICAgICAgICAgcmV0dXJuIFpFUk87XHJcbiAgICAgICAgaWYgKCFpc0xvbmcobXVsdGlwbGllcikpXHJcbiAgICAgICAgICAgIG11bHRpcGxpZXIgPSBmcm9tVmFsdWUobXVsdGlwbGllcik7XHJcbiAgICAgICAgaWYgKG11bHRpcGxpZXIuaXNaZXJvKCkpXHJcbiAgICAgICAgICAgIHJldHVybiBaRVJPO1xyXG4gICAgICAgIGlmICh0aGlzLmVxKE1JTl9WQUxVRSkpXHJcbiAgICAgICAgICAgIHJldHVybiBtdWx0aXBsaWVyLmlzT2RkKCkgPyBNSU5fVkFMVUUgOiBaRVJPO1xyXG4gICAgICAgIGlmIChtdWx0aXBsaWVyLmVxKE1JTl9WQUxVRSkpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmlzT2RkKCkgPyBNSU5fVkFMVUUgOiBaRVJPO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5pc05lZ2F0aXZlKCkpIHtcclxuICAgICAgICAgICAgaWYgKG11bHRpcGxpZXIuaXNOZWdhdGl2ZSgpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMubmVnKCkubXVsKG11bHRpcGxpZXIubmVnKCkpO1xyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5uZWcoKS5tdWwobXVsdGlwbGllcikubmVnKCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChtdWx0aXBsaWVyLmlzTmVnYXRpdmUoKSlcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMubXVsKG11bHRpcGxpZXIubmVnKCkpLm5lZygpO1xyXG5cclxuICAgICAgICAvLyBJZiBib3RoIGxvbmdzIGFyZSBzbWFsbCwgdXNlIGZsb2F0IG11bHRpcGxpY2F0aW9uXHJcbiAgICAgICAgaWYgKHRoaXMubHQoVFdPX1BXUl8yNCkgJiYgbXVsdGlwbGllci5sdChUV09fUFdSXzI0KSlcclxuICAgICAgICAgICAgcmV0dXJuIGZyb21OdW1iZXIodGhpcy50b051bWJlcigpICogbXVsdGlwbGllci50b051bWJlcigpLCB0aGlzLnVuc2lnbmVkKTtcclxuXHJcbiAgICAgICAgLy8gRGl2aWRlIGVhY2ggbG9uZyBpbnRvIDQgY2h1bmtzIG9mIDE2IGJpdHMsIGFuZCB0aGVuIGFkZCB1cCA0eDQgcHJvZHVjdHMuXHJcbiAgICAgICAgLy8gV2UgY2FuIHNraXAgcHJvZHVjdHMgdGhhdCB3b3VsZCBvdmVyZmxvdy5cclxuXHJcbiAgICAgICAgdmFyIGE0OCA9IHRoaXMuaGlnaCA+Pj4gMTY7XHJcbiAgICAgICAgdmFyIGEzMiA9IHRoaXMuaGlnaCAmIDB4RkZGRjtcclxuICAgICAgICB2YXIgYTE2ID0gdGhpcy5sb3cgPj4+IDE2O1xyXG4gICAgICAgIHZhciBhMDAgPSB0aGlzLmxvdyAmIDB4RkZGRjtcclxuXHJcbiAgICAgICAgdmFyIGI0OCA9IG11bHRpcGxpZXIuaGlnaCA+Pj4gMTY7XHJcbiAgICAgICAgdmFyIGIzMiA9IG11bHRpcGxpZXIuaGlnaCAmIDB4RkZGRjtcclxuICAgICAgICB2YXIgYjE2ID0gbXVsdGlwbGllci5sb3cgPj4+IDE2O1xyXG4gICAgICAgIHZhciBiMDAgPSBtdWx0aXBsaWVyLmxvdyAmIDB4RkZGRjtcclxuXHJcbiAgICAgICAgdmFyIGM0OCA9IDAsIGMzMiA9IDAsIGMxNiA9IDAsIGMwMCA9IDA7XHJcbiAgICAgICAgYzAwICs9IGEwMCAqIGIwMDtcclxuICAgICAgICBjMTYgKz0gYzAwID4+PiAxNjtcclxuICAgICAgICBjMDAgJj0gMHhGRkZGO1xyXG4gICAgICAgIGMxNiArPSBhMTYgKiBiMDA7XHJcbiAgICAgICAgYzMyICs9IGMxNiA+Pj4gMTY7XHJcbiAgICAgICAgYzE2ICY9IDB4RkZGRjtcclxuICAgICAgICBjMTYgKz0gYTAwICogYjE2O1xyXG4gICAgICAgIGMzMiArPSBjMTYgPj4+IDE2O1xyXG4gICAgICAgIGMxNiAmPSAweEZGRkY7XHJcbiAgICAgICAgYzMyICs9IGEzMiAqIGIwMDtcclxuICAgICAgICBjNDggKz0gYzMyID4+PiAxNjtcclxuICAgICAgICBjMzIgJj0gMHhGRkZGO1xyXG4gICAgICAgIGMzMiArPSBhMTYgKiBiMTY7XHJcbiAgICAgICAgYzQ4ICs9IGMzMiA+Pj4gMTY7XHJcbiAgICAgICAgYzMyICY9IDB4RkZGRjtcclxuICAgICAgICBjMzIgKz0gYTAwICogYjMyO1xyXG4gICAgICAgIGM0OCArPSBjMzIgPj4+IDE2O1xyXG4gICAgICAgIGMzMiAmPSAweEZGRkY7XHJcbiAgICAgICAgYzQ4ICs9IGE0OCAqIGIwMCArIGEzMiAqIGIxNiArIGExNiAqIGIzMiArIGEwMCAqIGI0ODtcclxuICAgICAgICBjNDggJj0gMHhGRkZGO1xyXG4gICAgICAgIHJldHVybiBmcm9tQml0cygoYzE2IDw8IDE2KSB8IGMwMCwgKGM0OCA8PCAxNikgfCBjMzIsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhlIHByb2R1Y3Qgb2YgdGhpcyBhbmQgdGhlIHNwZWNpZmllZCBMb25nLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI211bHRpcGx5fS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBtdWx0aXBsaWVyIE11bHRpcGxpZXJcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gUHJvZHVjdFxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLm11bCA9IExvbmdQcm90b3R5cGUubXVsdGlwbHk7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoaXMgTG9uZyBkaXZpZGVkIGJ5IHRoZSBzcGVjaWZpZWQuIFRoZSByZXN1bHQgaXMgc2lnbmVkIGlmIHRoaXMgTG9uZyBpcyBzaWduZWQgb3JcclxuICAgICAqICB1bnNpZ25lZCBpZiB0aGlzIExvbmcgaXMgdW5zaWduZWQuXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IGRpdmlzb3IgRGl2aXNvclxyXG4gICAgICogQHJldHVybnMgeyFMb25nfSBRdW90aWVudFxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLmRpdmlkZSA9IGZ1bmN0aW9uIGRpdmlkZShkaXZpc29yKSB7XHJcbiAgICAgICAgaWYgKCFpc0xvbmcoZGl2aXNvcikpXHJcbiAgICAgICAgICAgIGRpdmlzb3IgPSBmcm9tVmFsdWUoZGl2aXNvcik7XHJcbiAgICAgICAgaWYgKGRpdmlzb3IuaXNaZXJvKCkpXHJcbiAgICAgICAgICAgIHRocm93IEVycm9yKCdkaXZpc2lvbiBieSB6ZXJvJyk7XHJcbiAgICAgICAgaWYgKHRoaXMuaXNaZXJvKCkpXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnVuc2lnbmVkID8gVVpFUk8gOiBaRVJPO1xyXG4gICAgICAgIHZhciBhcHByb3gsIHJlbSwgcmVzO1xyXG4gICAgICAgIGlmICghdGhpcy51bnNpZ25lZCkge1xyXG4gICAgICAgICAgICAvLyBUaGlzIHNlY3Rpb24gaXMgb25seSByZWxldmFudCBmb3Igc2lnbmVkIGxvbmdzIGFuZCBpcyBkZXJpdmVkIGZyb20gdGhlXHJcbiAgICAgICAgICAgIC8vIGNsb3N1cmUgbGlicmFyeSBhcyBhIHdob2xlLlxyXG4gICAgICAgICAgICBpZiAodGhpcy5lcShNSU5fVkFMVUUpKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZGl2aXNvci5lcShPTkUpIHx8IGRpdmlzb3IuZXEoTkVHX09ORSkpXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE1JTl9WQUxVRTsgIC8vIHJlY2FsbCB0aGF0IC1NSU5fVkFMVUUgPT0gTUlOX1ZBTFVFXHJcbiAgICAgICAgICAgICAgICBlbHNlIGlmIChkaXZpc29yLmVxKE1JTl9WQUxVRSkpXHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIE9ORTtcclxuICAgICAgICAgICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIGhhdmUgfG90aGVyfCA+PSAyLCBzbyB8dGhpcy9vdGhlcnwgPCB8TUlOX1ZBTFVFfC5cclxuICAgICAgICAgICAgICAgICAgICB2YXIgaGFsZlRoaXMgPSB0aGlzLnNocigxKTtcclxuICAgICAgICAgICAgICAgICAgICBhcHByb3ggPSBoYWxmVGhpcy5kaXYoZGl2aXNvcikuc2hsKDEpO1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChhcHByb3guZXEoWkVSTykpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGRpdmlzb3IuaXNOZWdhdGl2ZSgpID8gT05FIDogTkVHX09ORTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZW0gPSB0aGlzLnN1YihkaXZpc29yLm11bChhcHByb3gpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzID0gYXBwcm94LmFkZChyZW0uZGl2KGRpdmlzb3IpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHJlcztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZGl2aXNvci5lcShNSU5fVkFMVUUpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMudW5zaWduZWQgPyBVWkVSTyA6IFpFUk87XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmlzTmVnYXRpdmUoKSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKGRpdmlzb3IuaXNOZWdhdGl2ZSgpKVxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm5lZygpLmRpdihkaXZpc29yLm5lZygpKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLm5lZygpLmRpdihkaXZpc29yKS5uZWcoKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChkaXZpc29yLmlzTmVnYXRpdmUoKSlcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLmRpdihkaXZpc29yLm5lZygpKS5uZWcoKTtcclxuICAgICAgICAgICAgcmVzID0gWkVSTztcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBUaGUgYWxnb3JpdGhtIGJlbG93IGhhcyBub3QgYmVlbiBtYWRlIGZvciB1bnNpZ25lZCBsb25ncy4gSXQncyB0aGVyZWZvcmVcclxuICAgICAgICAgICAgLy8gcmVxdWlyZWQgdG8gdGFrZSBzcGVjaWFsIGNhcmUgb2YgdGhlIE1TQiBwcmlvciB0byBydW5uaW5nIGl0LlxyXG4gICAgICAgICAgICBpZiAoIWRpdmlzb3IudW5zaWduZWQpXHJcbiAgICAgICAgICAgICAgICBkaXZpc29yID0gZGl2aXNvci50b1Vuc2lnbmVkKCk7XHJcbiAgICAgICAgICAgIGlmIChkaXZpc29yLmd0KHRoaXMpKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFVaRVJPO1xyXG4gICAgICAgICAgICBpZiAoZGl2aXNvci5ndCh0aGlzLnNocnUoMSkpKSAvLyAxNSA+Pj4gMSA9IDcgOyB3aXRoIGRpdmlzb3IgPSA4IDsgdHJ1ZVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFVPTkU7XHJcbiAgICAgICAgICAgIHJlcyA9IFVaRVJPO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gUmVwZWF0IHRoZSBmb2xsb3dpbmcgdW50aWwgdGhlIHJlbWFpbmRlciBpcyBsZXNzIHRoYW4gb3RoZXI6ICBmaW5kIGFcclxuICAgICAgICAvLyBmbG9hdGluZy1wb2ludCB0aGF0IGFwcHJveGltYXRlcyByZW1haW5kZXIgLyBvdGhlciAqZnJvbSBiZWxvdyosIGFkZCB0aGlzXHJcbiAgICAgICAgLy8gaW50byB0aGUgcmVzdWx0LCBhbmQgc3VidHJhY3QgaXQgZnJvbSB0aGUgcmVtYWluZGVyLiAgSXQgaXMgY3JpdGljYWwgdGhhdFxyXG4gICAgICAgIC8vIHRoZSBhcHByb3hpbWF0ZSB2YWx1ZSBpcyBsZXNzIHRoYW4gb3IgZXF1YWwgdG8gdGhlIHJlYWwgdmFsdWUgc28gdGhhdCB0aGVcclxuICAgICAgICAvLyByZW1haW5kZXIgbmV2ZXIgYmVjb21lcyBuZWdhdGl2ZS5cclxuICAgICAgICByZW0gPSB0aGlzO1xyXG4gICAgICAgIHdoaWxlIChyZW0uZ3RlKGRpdmlzb3IpKSB7XHJcbiAgICAgICAgICAgIC8vIEFwcHJveGltYXRlIHRoZSByZXN1bHQgb2YgZGl2aXNpb24uIFRoaXMgbWF5IGJlIGEgbGl0dGxlIGdyZWF0ZXIgb3JcclxuICAgICAgICAgICAgLy8gc21hbGxlciB0aGFuIHRoZSBhY3R1YWwgdmFsdWUuXHJcbiAgICAgICAgICAgIGFwcHJveCA9IE1hdGgubWF4KDEsIE1hdGguZmxvb3IocmVtLnRvTnVtYmVyKCkgLyBkaXZpc29yLnRvTnVtYmVyKCkpKTtcclxuXHJcbiAgICAgICAgICAgIC8vIFdlIHdpbGwgdHdlYWsgdGhlIGFwcHJveGltYXRlIHJlc3VsdCBieSBjaGFuZ2luZyBpdCBpbiB0aGUgNDgtdGggZGlnaXQgb3JcclxuICAgICAgICAgICAgLy8gdGhlIHNtYWxsZXN0IG5vbi1mcmFjdGlvbmFsIGRpZ2l0LCB3aGljaGV2ZXIgaXMgbGFyZ2VyLlxyXG4gICAgICAgICAgICB2YXIgbG9nMiA9IE1hdGguY2VpbChNYXRoLmxvZyhhcHByb3gpIC8gTWF0aC5MTjIpLFxyXG4gICAgICAgICAgICAgICAgZGVsdGEgPSAobG9nMiA8PSA0OCkgPyAxIDogcG93X2RibCgyLCBsb2cyIC0gNDgpLFxyXG5cclxuICAgICAgICAgICAgLy8gRGVjcmVhc2UgdGhlIGFwcHJveGltYXRpb24gdW50aWwgaXQgaXMgc21hbGxlciB0aGFuIHRoZSByZW1haW5kZXIuICBOb3RlXHJcbiAgICAgICAgICAgIC8vIHRoYXQgaWYgaXQgaXMgdG9vIGxhcmdlLCB0aGUgcHJvZHVjdCBvdmVyZmxvd3MgYW5kIGlzIG5lZ2F0aXZlLlxyXG4gICAgICAgICAgICAgICAgYXBwcm94UmVzID0gZnJvbU51bWJlcihhcHByb3gpLFxyXG4gICAgICAgICAgICAgICAgYXBwcm94UmVtID0gYXBwcm94UmVzLm11bChkaXZpc29yKTtcclxuICAgICAgICAgICAgd2hpbGUgKGFwcHJveFJlbS5pc05lZ2F0aXZlKCkgfHwgYXBwcm94UmVtLmd0KHJlbSkpIHtcclxuICAgICAgICAgICAgICAgIGFwcHJveCAtPSBkZWx0YTtcclxuICAgICAgICAgICAgICAgIGFwcHJveFJlcyA9IGZyb21OdW1iZXIoYXBwcm94LCB0aGlzLnVuc2lnbmVkKTtcclxuICAgICAgICAgICAgICAgIGFwcHJveFJlbSA9IGFwcHJveFJlcy5tdWwoZGl2aXNvcik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIFdlIGtub3cgdGhlIGFuc3dlciBjYW4ndCBiZSB6ZXJvLi4uIGFuZCBhY3R1YWxseSwgemVybyB3b3VsZCBjYXVzZVxyXG4gICAgICAgICAgICAvLyBpbmZpbml0ZSByZWN1cnNpb24gc2luY2Ugd2Ugd291bGQgbWFrZSBubyBwcm9ncmVzcy5cclxuICAgICAgICAgICAgaWYgKGFwcHJveFJlcy5pc1plcm8oKSlcclxuICAgICAgICAgICAgICAgIGFwcHJveFJlcyA9IE9ORTtcclxuXHJcbiAgICAgICAgICAgIHJlcyA9IHJlcy5hZGQoYXBwcm94UmVzKTtcclxuICAgICAgICAgICAgcmVtID0gcmVtLnN1YihhcHByb3hSZW0pO1xyXG4gICAgICAgIH1cclxuICAgICAgICByZXR1cm4gcmVzO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhpcyBMb25nIGRpdmlkZWQgYnkgdGhlIHNwZWNpZmllZC4gVGhpcyBpcyBhbiBhbGlhcyBvZiB7QGxpbmsgTG9uZyNkaXZpZGV9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IGRpdmlzb3IgRGl2aXNvclxyXG4gICAgICogQHJldHVybnMgeyFMb25nfSBRdW90aWVudFxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLmRpdiA9IExvbmdQcm90b3R5cGUuZGl2aWRlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGlzIExvbmcgbW9kdWxvIHRoZSBzcGVjaWZpZWQuXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IGRpdmlzb3IgRGl2aXNvclxyXG4gICAgICogQHJldHVybnMgeyFMb25nfSBSZW1haW5kZXJcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5tb2R1bG8gPSBmdW5jdGlvbiBtb2R1bG8oZGl2aXNvcikge1xyXG4gICAgICAgIGlmICghaXNMb25nKGRpdmlzb3IpKVxyXG4gICAgICAgICAgICBkaXZpc29yID0gZnJvbVZhbHVlKGRpdmlzb3IpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLnN1Yih0aGlzLmRpdihkaXZpc29yKS5tdWwoZGl2aXNvcikpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhpcyBMb25nIG1vZHVsbyB0aGUgc3BlY2lmaWVkLiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI21vZHVsb30uXHJcbiAgICAgKiBAZnVuY3Rpb25cclxuICAgICAqIEBwYXJhbSB7IUxvbmd8bnVtYmVyfHN0cmluZ30gZGl2aXNvciBEaXZpc29yXHJcbiAgICAgKiBAcmV0dXJucyB7IUxvbmd9IFJlbWFpbmRlclxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLm1vZCA9IExvbmdQcm90b3R5cGUubW9kdWxvO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgYml0d2lzZSBOT1Qgb2YgdGhpcyBMb25nLlxyXG4gICAgICogQHJldHVybnMgeyFMb25nfVxyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLm5vdCA9IGZ1bmN0aW9uIG5vdCgpIHtcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHMofnRoaXMubG93LCB+dGhpcy5oaWdoLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoZSBiaXR3aXNlIEFORCBvZiB0aGlzIExvbmcgYW5kIHRoZSBzcGVjaWZpZWQuXHJcbiAgICAgKiBAcGFyYW0geyFMb25nfG51bWJlcnxzdHJpbmd9IG90aGVyIE90aGVyIExvbmdcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ31cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5hbmQgPSBmdW5jdGlvbiBhbmQob3RoZXIpIHtcclxuICAgICAgICBpZiAoIWlzTG9uZyhvdGhlcikpXHJcbiAgICAgICAgICAgIG90aGVyID0gZnJvbVZhbHVlKG90aGVyKTtcclxuICAgICAgICByZXR1cm4gZnJvbUJpdHModGhpcy5sb3cgJiBvdGhlci5sb3csIHRoaXMuaGlnaCAmIG90aGVyLmhpZ2gsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhlIGJpdHdpc2UgT1Igb2YgdGhpcyBMb25nIGFuZCB0aGUgc3BlY2lmaWVkLlxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciBMb25nXHJcbiAgICAgKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUub3IgPSBmdW5jdGlvbiBvcihvdGhlcikge1xyXG4gICAgICAgIGlmICghaXNMb25nKG90aGVyKSlcclxuICAgICAgICAgICAgb3RoZXIgPSBmcm9tVmFsdWUob3RoZXIpO1xyXG4gICAgICAgIHJldHVybiBmcm9tQml0cyh0aGlzLmxvdyB8IG90aGVyLmxvdywgdGhpcy5oaWdoIHwgb3RoZXIuaGlnaCwgdGhpcy51bnNpZ25lZCk7XHJcbiAgICB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgYml0d2lzZSBYT1Igb2YgdGhpcyBMb25nIGFuZCB0aGUgZ2l2ZW4gb25lLlxyXG4gICAgICogQHBhcmFtIHshTG9uZ3xudW1iZXJ8c3RyaW5nfSBvdGhlciBPdGhlciBMb25nXHJcbiAgICAgKiBAcmV0dXJucyB7IUxvbmd9XHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUueG9yID0gZnVuY3Rpb24geG9yKG90aGVyKSB7XHJcbiAgICAgICAgaWYgKCFpc0xvbmcob3RoZXIpKVxyXG4gICAgICAgICAgICBvdGhlciA9IGZyb21WYWx1ZShvdGhlcik7XHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93IF4gb3RoZXIubG93LCB0aGlzLmhpZ2ggXiBvdGhlci5oaWdoLCB0aGlzLnVuc2lnbmVkKTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgc2hpZnRlZCB0byB0aGUgbGVmdCBieSB0aGUgZ2l2ZW4gYW1vdW50LlxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IG51bUJpdHMgTnVtYmVyIG9mIGJpdHNcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gU2hpZnRlZCBMb25nXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuc2hpZnRMZWZ0ID0gZnVuY3Rpb24gc2hpZnRMZWZ0KG51bUJpdHMpIHtcclxuICAgICAgICBpZiAoaXNMb25nKG51bUJpdHMpKVxyXG4gICAgICAgICAgICBudW1CaXRzID0gbnVtQml0cy50b0ludCgpO1xyXG4gICAgICAgIGlmICgobnVtQml0cyAmPSA2MykgPT09IDApXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIGVsc2UgaWYgKG51bUJpdHMgPCAzMilcclxuICAgICAgICAgICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93IDw8IG51bUJpdHMsICh0aGlzLmhpZ2ggPDwgbnVtQml0cykgfCAodGhpcy5sb3cgPj4+ICgzMiAtIG51bUJpdHMpKSwgdGhpcy51bnNpZ25lZCk7XHJcbiAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICByZXR1cm4gZnJvbUJpdHMoMCwgdGhpcy5sb3cgPDwgKG51bUJpdHMgLSAzMiksIHRoaXMudW5zaWduZWQpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhpcyBMb25nIHdpdGggYml0cyBzaGlmdGVkIHRvIHRoZSBsZWZ0IGJ5IHRoZSBnaXZlbiBhbW91bnQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjc2hpZnRMZWZ0fS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IG51bUJpdHMgTnVtYmVyIG9mIGJpdHNcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gU2hpZnRlZCBMb25nXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuc2hsID0gTG9uZ1Byb3RvdHlwZS5zaGlmdExlZnQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgYXJpdGhtZXRpY2FsbHkgc2hpZnRlZCB0byB0aGUgcmlnaHQgYnkgdGhlIGdpdmVuIGFtb3VudC5cclxuICAgICAqIEBwYXJhbSB7bnVtYmVyfCFMb25nfSBudW1CaXRzIE51bWJlciBvZiBiaXRzXHJcbiAgICAgKiBAcmV0dXJucyB7IUxvbmd9IFNoaWZ0ZWQgTG9uZ1xyXG4gICAgICovXHJcbiAgICBMb25nUHJvdG90eXBlLnNoaWZ0UmlnaHQgPSBmdW5jdGlvbiBzaGlmdFJpZ2h0KG51bUJpdHMpIHtcclxuICAgICAgICBpZiAoaXNMb25nKG51bUJpdHMpKVxyXG4gICAgICAgICAgICBudW1CaXRzID0gbnVtQml0cy50b0ludCgpO1xyXG4gICAgICAgIGlmICgobnVtQml0cyAmPSA2MykgPT09IDApXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xyXG4gICAgICAgIGVsc2UgaWYgKG51bUJpdHMgPCAzMilcclxuICAgICAgICAgICAgcmV0dXJuIGZyb21CaXRzKCh0aGlzLmxvdyA+Pj4gbnVtQml0cykgfCAodGhpcy5oaWdoIDw8ICgzMiAtIG51bUJpdHMpKSwgdGhpcy5oaWdoID4+IG51bUJpdHMsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgICAgIGVsc2VcclxuICAgICAgICAgICAgcmV0dXJuIGZyb21CaXRzKHRoaXMuaGlnaCA+PiAobnVtQml0cyAtIDMyKSwgdGhpcy5oaWdoID49IDAgPyAwIDogLTEsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhpcyBMb25nIHdpdGggYml0cyBhcml0aG1ldGljYWxseSBzaGlmdGVkIHRvIHRoZSByaWdodCBieSB0aGUgZ2l2ZW4gYW1vdW50LiBUaGlzIGlzIGFuIGFsaWFzIG9mIHtAbGluayBMb25nI3NoaWZ0UmlnaHR9LlxyXG4gICAgICogQGZ1bmN0aW9uXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gICAgICogQHJldHVybnMgeyFMb25nfSBTaGlmdGVkIExvbmdcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5zaHIgPSBMb25nUHJvdG90eXBlLnNoaWZ0UmlnaHQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgbG9naWNhbGx5IHNoaWZ0ZWQgdG8gdGhlIHJpZ2h0IGJ5IHRoZSBnaXZlbiBhbW91bnQuXHJcbiAgICAgKiBAcGFyYW0ge251bWJlcnwhTG9uZ30gbnVtQml0cyBOdW1iZXIgb2YgYml0c1xyXG4gICAgICogQHJldHVybnMgeyFMb25nfSBTaGlmdGVkIExvbmdcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS5zaGlmdFJpZ2h0VW5zaWduZWQgPSBmdW5jdGlvbiBzaGlmdFJpZ2h0VW5zaWduZWQobnVtQml0cykge1xyXG4gICAgICAgIGlmIChpc0xvbmcobnVtQml0cykpXHJcbiAgICAgICAgICAgIG51bUJpdHMgPSBudW1CaXRzLnRvSW50KCk7XHJcbiAgICAgICAgbnVtQml0cyAmPSA2MztcclxuICAgICAgICBpZiAobnVtQml0cyA9PT0gMClcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgZWxzZSB7XHJcbiAgICAgICAgICAgIHZhciBoaWdoID0gdGhpcy5oaWdoO1xyXG4gICAgICAgICAgICBpZiAobnVtQml0cyA8IDMyKSB7XHJcbiAgICAgICAgICAgICAgICB2YXIgbG93ID0gdGhpcy5sb3c7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZnJvbUJpdHMoKGxvdyA+Pj4gbnVtQml0cykgfCAoaGlnaCA8PCAoMzIgLSBudW1CaXRzKSksIGhpZ2ggPj4+IG51bUJpdHMsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG51bUJpdHMgPT09IDMyKVxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZyb21CaXRzKGhpZ2gsIDAsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZnJvbUJpdHMoaGlnaCA+Pj4gKG51bUJpdHMgLSAzMiksIDAsIHRoaXMudW5zaWduZWQpO1xyXG4gICAgICAgIH1cclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoaXMgTG9uZyB3aXRoIGJpdHMgbG9naWNhbGx5IHNoaWZ0ZWQgdG8gdGhlIHJpZ2h0IGJ5IHRoZSBnaXZlbiBhbW91bnQuIFRoaXMgaXMgYW4gYWxpYXMgb2Yge0BsaW5rIExvbmcjc2hpZnRSaWdodFVuc2lnbmVkfS5cclxuICAgICAqIEBmdW5jdGlvblxyXG4gICAgICogQHBhcmFtIHtudW1iZXJ8IUxvbmd9IG51bUJpdHMgTnVtYmVyIG9mIGJpdHNcclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gU2hpZnRlZCBMb25nXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUuc2hydSA9IExvbmdQcm90b3R5cGUuc2hpZnRSaWdodFVuc2lnbmVkO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ29udmVydHMgdGhpcyBMb25nIHRvIHNpZ25lZC5cclxuICAgICAqIEByZXR1cm5zIHshTG9uZ30gU2lnbmVkIGxvbmdcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS50b1NpZ25lZCA9IGZ1bmN0aW9uIHRvU2lnbmVkKCkge1xyXG4gICAgICAgIGlmICghdGhpcy51bnNpZ25lZClcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93LCB0aGlzLmhpZ2gsIGZhbHNlKTtcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDb252ZXJ0cyB0aGlzIExvbmcgdG8gdW5zaWduZWQuXHJcbiAgICAgKiBAcmV0dXJucyB7IUxvbmd9IFVuc2lnbmVkIGxvbmdcclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS50b1Vuc2lnbmVkID0gZnVuY3Rpb24gdG9VbnNpZ25lZCgpIHtcclxuICAgICAgICBpZiAodGhpcy51bnNpZ25lZClcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XHJcbiAgICAgICAgcmV0dXJuIGZyb21CaXRzKHRoaXMubG93LCB0aGlzLmhpZ2gsIHRydWUpO1xyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnZlcnRzIHRoaXMgTG9uZyB0byBpdHMgYnl0ZSByZXByZXNlbnRhdGlvbi5cclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbj19IGxlIFdoZXRoZXIgbGl0dGxlIG9yIGJpZyBlbmRpYW4sIGRlZmF1bHRzIHRvIGJpZyBlbmRpYW5cclxuICAgICAqIEByZXR1cm5zIHshQXJyYXkuPG51bWJlcj59IEJ5dGUgcmVwcmVzZW50YXRpb25cclxuICAgICAqL1xyXG4gICAgTG9uZ1Byb3RvdHlwZS50b0J5dGVzID0gZnVuY3Rpb24obGUpIHtcclxuICAgICAgICByZXR1cm4gbGUgPyB0aGlzLnRvQnl0ZXNMRSgpIDogdGhpcy50b0J5dGVzQkUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnZlcnRzIHRoaXMgTG9uZyB0byBpdHMgbGl0dGxlIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uLlxyXG4gICAgICogQHJldHVybnMgeyFBcnJheS48bnVtYmVyPn0gTGl0dGxlIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUudG9CeXRlc0xFID0gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgdmFyIGhpID0gdGhpcy5oaWdoLFxyXG4gICAgICAgICAgICBsbyA9IHRoaXMubG93O1xyXG4gICAgICAgIHJldHVybiBbXHJcbiAgICAgICAgICAgICBsbyAgICAgICAgICYgMHhmZixcclxuICAgICAgICAgICAgKGxvID4+PiAgOCkgJiAweGZmLFxyXG4gICAgICAgICAgICAobG8gPj4+IDE2KSAmIDB4ZmYsXHJcbiAgICAgICAgICAgIChsbyA+Pj4gMjQpICYgMHhmZixcclxuICAgICAgICAgICAgIGhpICAgICAgICAgJiAweGZmLFxyXG4gICAgICAgICAgICAoaGkgPj4+ICA4KSAmIDB4ZmYsXHJcbiAgICAgICAgICAgIChoaSA+Pj4gMTYpICYgMHhmZixcclxuICAgICAgICAgICAgKGhpID4+PiAyNCkgJiAweGZmXHJcbiAgICAgICAgXTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENvbnZlcnRzIHRoaXMgTG9uZyB0byBpdHMgYmlnIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uLlxyXG4gICAgICogQHJldHVybnMgeyFBcnJheS48bnVtYmVyPn0gQmlnIGVuZGlhbiBieXRlIHJlcHJlc2VudGF0aW9uXHJcbiAgICAgKi9cclxuICAgIExvbmdQcm90b3R5cGUudG9CeXRlc0JFID0gZnVuY3Rpb24oKSB7XHJcbiAgICAgICAgdmFyIGhpID0gdGhpcy5oaWdoLFxyXG4gICAgICAgICAgICBsbyA9IHRoaXMubG93O1xyXG4gICAgICAgIHJldHVybiBbXHJcbiAgICAgICAgICAgIChoaSA+Pj4gMjQpICYgMHhmZixcclxuICAgICAgICAgICAgKGhpID4+PiAxNikgJiAweGZmLFxyXG4gICAgICAgICAgICAoaGkgPj4+ICA4KSAmIDB4ZmYsXHJcbiAgICAgICAgICAgICBoaSAgICAgICAgICYgMHhmZixcclxuICAgICAgICAgICAgKGxvID4+PiAyNCkgJiAweGZmLFxyXG4gICAgICAgICAgICAobG8gPj4+IDE2KSAmIDB4ZmYsXHJcbiAgICAgICAgICAgIChsbyA+Pj4gIDgpICYgMHhmZixcclxuICAgICAgICAgICAgIGxvICAgICAgICAgJiAweGZmXHJcbiAgICAgICAgXTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gTG9uZztcclxufSk7XHJcbiIsIid1c2Ugc3RyaWN0J1xudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIEhhc2hCYXNlID0gcmVxdWlyZSgnaGFzaC1iYXNlJylcblxudmFyIEFSUkFZMTYgPSBuZXcgQXJyYXkoMTYpXG5cbmZ1bmN0aW9uIE1ENSAoKSB7XG4gIEhhc2hCYXNlLmNhbGwodGhpcywgNjQpXG5cbiAgLy8gc3RhdGVcbiAgdGhpcy5fYSA9IDB4Njc0NTIzMDFcbiAgdGhpcy5fYiA9IDB4ZWZjZGFiODlcbiAgdGhpcy5fYyA9IDB4OThiYWRjZmVcbiAgdGhpcy5fZCA9IDB4MTAzMjU0NzZcbn1cblxuaW5oZXJpdHMoTUQ1LCBIYXNoQmFzZSlcblxuTUQ1LnByb3RvdHlwZS5fdXBkYXRlID0gZnVuY3Rpb24gKCkge1xuICB2YXIgTSA9IEFSUkFZMTZcbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgKytpKSBNW2ldID0gdGhpcy5fYmxvY2sucmVhZEludDMyTEUoaSAqIDQpXG5cbiAgdmFyIGEgPSB0aGlzLl9hXG4gIHZhciBiID0gdGhpcy5fYlxuICB2YXIgYyA9IHRoaXMuX2NcbiAgdmFyIGQgPSB0aGlzLl9kXG5cbiAgYSA9IGZuRihhLCBiLCBjLCBkLCBNWzBdLCAweGQ3NmFhNDc4LCA3KVxuICBkID0gZm5GKGQsIGEsIGIsIGMsIE1bMV0sIDB4ZThjN2I3NTYsIDEyKVxuICBjID0gZm5GKGMsIGQsIGEsIGIsIE1bMl0sIDB4MjQyMDcwZGIsIDE3KVxuICBiID0gZm5GKGIsIGMsIGQsIGEsIE1bM10sIDB4YzFiZGNlZWUsIDIyKVxuICBhID0gZm5GKGEsIGIsIGMsIGQsIE1bNF0sIDB4ZjU3YzBmYWYsIDcpXG4gIGQgPSBmbkYoZCwgYSwgYiwgYywgTVs1XSwgMHg0Nzg3YzYyYSwgMTIpXG4gIGMgPSBmbkYoYywgZCwgYSwgYiwgTVs2XSwgMHhhODMwNDYxMywgMTcpXG4gIGIgPSBmbkYoYiwgYywgZCwgYSwgTVs3XSwgMHhmZDQ2OTUwMSwgMjIpXG4gIGEgPSBmbkYoYSwgYiwgYywgZCwgTVs4XSwgMHg2OTgwOThkOCwgNylcbiAgZCA9IGZuRihkLCBhLCBiLCBjLCBNWzldLCAweDhiNDRmN2FmLCAxMilcbiAgYyA9IGZuRihjLCBkLCBhLCBiLCBNWzEwXSwgMHhmZmZmNWJiMSwgMTcpXG4gIGIgPSBmbkYoYiwgYywgZCwgYSwgTVsxMV0sIDB4ODk1Y2Q3YmUsIDIyKVxuICBhID0gZm5GKGEsIGIsIGMsIGQsIE1bMTJdLCAweDZiOTAxMTIyLCA3KVxuICBkID0gZm5GKGQsIGEsIGIsIGMsIE1bMTNdLCAweGZkOTg3MTkzLCAxMilcbiAgYyA9IGZuRihjLCBkLCBhLCBiLCBNWzE0XSwgMHhhNjc5NDM4ZSwgMTcpXG4gIGIgPSBmbkYoYiwgYywgZCwgYSwgTVsxNV0sIDB4NDliNDA4MjEsIDIyKVxuXG4gIGEgPSBmbkcoYSwgYiwgYywgZCwgTVsxXSwgMHhmNjFlMjU2MiwgNSlcbiAgZCA9IGZuRyhkLCBhLCBiLCBjLCBNWzZdLCAweGMwNDBiMzQwLCA5KVxuICBjID0gZm5HKGMsIGQsIGEsIGIsIE1bMTFdLCAweDI2NWU1YTUxLCAxNClcbiAgYiA9IGZuRyhiLCBjLCBkLCBhLCBNWzBdLCAweGU5YjZjN2FhLCAyMClcbiAgYSA9IGZuRyhhLCBiLCBjLCBkLCBNWzVdLCAweGQ2MmYxMDVkLCA1KVxuICBkID0gZm5HKGQsIGEsIGIsIGMsIE1bMTBdLCAweDAyNDQxNDUzLCA5KVxuICBjID0gZm5HKGMsIGQsIGEsIGIsIE1bMTVdLCAweGQ4YTFlNjgxLCAxNClcbiAgYiA9IGZuRyhiLCBjLCBkLCBhLCBNWzRdLCAweGU3ZDNmYmM4LCAyMClcbiAgYSA9IGZuRyhhLCBiLCBjLCBkLCBNWzldLCAweDIxZTFjZGU2LCA1KVxuICBkID0gZm5HKGQsIGEsIGIsIGMsIE1bMTRdLCAweGMzMzcwN2Q2LCA5KVxuICBjID0gZm5HKGMsIGQsIGEsIGIsIE1bM10sIDB4ZjRkNTBkODcsIDE0KVxuICBiID0gZm5HKGIsIGMsIGQsIGEsIE1bOF0sIDB4NDU1YTE0ZWQsIDIwKVxuICBhID0gZm5HKGEsIGIsIGMsIGQsIE1bMTNdLCAweGE5ZTNlOTA1LCA1KVxuICBkID0gZm5HKGQsIGEsIGIsIGMsIE1bMl0sIDB4ZmNlZmEzZjgsIDkpXG4gIGMgPSBmbkcoYywgZCwgYSwgYiwgTVs3XSwgMHg2NzZmMDJkOSwgMTQpXG4gIGIgPSBmbkcoYiwgYywgZCwgYSwgTVsxMl0sIDB4OGQyYTRjOGEsIDIwKVxuXG4gIGEgPSBmbkgoYSwgYiwgYywgZCwgTVs1XSwgMHhmZmZhMzk0MiwgNClcbiAgZCA9IGZuSChkLCBhLCBiLCBjLCBNWzhdLCAweDg3NzFmNjgxLCAxMSlcbiAgYyA9IGZuSChjLCBkLCBhLCBiLCBNWzExXSwgMHg2ZDlkNjEyMiwgMTYpXG4gIGIgPSBmbkgoYiwgYywgZCwgYSwgTVsxNF0sIDB4ZmRlNTM4MGMsIDIzKVxuICBhID0gZm5IKGEsIGIsIGMsIGQsIE1bMV0sIDB4YTRiZWVhNDQsIDQpXG4gIGQgPSBmbkgoZCwgYSwgYiwgYywgTVs0XSwgMHg0YmRlY2ZhOSwgMTEpXG4gIGMgPSBmbkgoYywgZCwgYSwgYiwgTVs3XSwgMHhmNmJiNGI2MCwgMTYpXG4gIGIgPSBmbkgoYiwgYywgZCwgYSwgTVsxMF0sIDB4YmViZmJjNzAsIDIzKVxuICBhID0gZm5IKGEsIGIsIGMsIGQsIE1bMTNdLCAweDI4OWI3ZWM2LCA0KVxuICBkID0gZm5IKGQsIGEsIGIsIGMsIE1bMF0sIDB4ZWFhMTI3ZmEsIDExKVxuICBjID0gZm5IKGMsIGQsIGEsIGIsIE1bM10sIDB4ZDRlZjMwODUsIDE2KVxuICBiID0gZm5IKGIsIGMsIGQsIGEsIE1bNl0sIDB4MDQ4ODFkMDUsIDIzKVxuICBhID0gZm5IKGEsIGIsIGMsIGQsIE1bOV0sIDB4ZDlkNGQwMzksIDQpXG4gIGQgPSBmbkgoZCwgYSwgYiwgYywgTVsxMl0sIDB4ZTZkYjk5ZTUsIDExKVxuICBjID0gZm5IKGMsIGQsIGEsIGIsIE1bMTVdLCAweDFmYTI3Y2Y4LCAxNilcbiAgYiA9IGZuSChiLCBjLCBkLCBhLCBNWzJdLCAweGM0YWM1NjY1LCAyMylcblxuICBhID0gZm5JKGEsIGIsIGMsIGQsIE1bMF0sIDB4ZjQyOTIyNDQsIDYpXG4gIGQgPSBmbkkoZCwgYSwgYiwgYywgTVs3XSwgMHg0MzJhZmY5NywgMTApXG4gIGMgPSBmbkkoYywgZCwgYSwgYiwgTVsxNF0sIDB4YWI5NDIzYTcsIDE1KVxuICBiID0gZm5JKGIsIGMsIGQsIGEsIE1bNV0sIDB4ZmM5M2EwMzksIDIxKVxuICBhID0gZm5JKGEsIGIsIGMsIGQsIE1bMTJdLCAweDY1NWI1OWMzLCA2KVxuICBkID0gZm5JKGQsIGEsIGIsIGMsIE1bM10sIDB4OGYwY2NjOTIsIDEwKVxuICBjID0gZm5JKGMsIGQsIGEsIGIsIE1bMTBdLCAweGZmZWZmNDdkLCAxNSlcbiAgYiA9IGZuSShiLCBjLCBkLCBhLCBNWzFdLCAweDg1ODQ1ZGQxLCAyMSlcbiAgYSA9IGZuSShhLCBiLCBjLCBkLCBNWzhdLCAweDZmYTg3ZTRmLCA2KVxuICBkID0gZm5JKGQsIGEsIGIsIGMsIE1bMTVdLCAweGZlMmNlNmUwLCAxMClcbiAgYyA9IGZuSShjLCBkLCBhLCBiLCBNWzZdLCAweGEzMDE0MzE0LCAxNSlcbiAgYiA9IGZuSShiLCBjLCBkLCBhLCBNWzEzXSwgMHg0ZTA4MTFhMSwgMjEpXG4gIGEgPSBmbkkoYSwgYiwgYywgZCwgTVs0XSwgMHhmNzUzN2U4MiwgNilcbiAgZCA9IGZuSShkLCBhLCBiLCBjLCBNWzExXSwgMHhiZDNhZjIzNSwgMTApXG4gIGMgPSBmbkkoYywgZCwgYSwgYiwgTVsyXSwgMHgyYWQ3ZDJiYiwgMTUpXG4gIGIgPSBmbkkoYiwgYywgZCwgYSwgTVs5XSwgMHhlYjg2ZDM5MSwgMjEpXG5cbiAgdGhpcy5fYSA9ICh0aGlzLl9hICsgYSkgfCAwXG4gIHRoaXMuX2IgPSAodGhpcy5fYiArIGIpIHwgMFxuICB0aGlzLl9jID0gKHRoaXMuX2MgKyBjKSB8IDBcbiAgdGhpcy5fZCA9ICh0aGlzLl9kICsgZCkgfCAwXG59XG5cbk1ENS5wcm90b3R5cGUuX2RpZ2VzdCA9IGZ1bmN0aW9uICgpIHtcbiAgLy8gY3JlYXRlIHBhZGRpbmcgYW5kIGhhbmRsZSBibG9ja3NcbiAgdGhpcy5fYmxvY2tbdGhpcy5fYmxvY2tPZmZzZXQrK10gPSAweDgwXG4gIGlmICh0aGlzLl9ibG9ja09mZnNldCA+IDU2KSB7XG4gICAgdGhpcy5fYmxvY2suZmlsbCgwLCB0aGlzLl9ibG9ja09mZnNldCwgNjQpXG4gICAgdGhpcy5fdXBkYXRlKClcbiAgICB0aGlzLl9ibG9ja09mZnNldCA9IDBcbiAgfVxuXG4gIHRoaXMuX2Jsb2NrLmZpbGwoMCwgdGhpcy5fYmxvY2tPZmZzZXQsIDU2KVxuICB0aGlzLl9ibG9jay53cml0ZVVJbnQzMkxFKHRoaXMuX2xlbmd0aFswXSwgNTYpXG4gIHRoaXMuX2Jsb2NrLndyaXRlVUludDMyTEUodGhpcy5fbGVuZ3RoWzFdLCA2MClcbiAgdGhpcy5fdXBkYXRlKClcblxuICAvLyBwcm9kdWNlIHJlc3VsdFxuICB2YXIgYnVmZmVyID0gbmV3IEJ1ZmZlcigxNilcbiAgYnVmZmVyLndyaXRlSW50MzJMRSh0aGlzLl9hLCAwKVxuICBidWZmZXIud3JpdGVJbnQzMkxFKHRoaXMuX2IsIDQpXG4gIGJ1ZmZlci53cml0ZUludDMyTEUodGhpcy5fYywgOClcbiAgYnVmZmVyLndyaXRlSW50MzJMRSh0aGlzLl9kLCAxMilcbiAgcmV0dXJuIGJ1ZmZlclxufVxuXG5mdW5jdGlvbiByb3RsICh4LCBuKSB7XG4gIHJldHVybiAoeCA8PCBuKSB8ICh4ID4+PiAoMzIgLSBuKSlcbn1cblxuZnVuY3Rpb24gZm5GIChhLCBiLCBjLCBkLCBtLCBrLCBzKSB7XG4gIHJldHVybiAocm90bCgoYSArICgoYiAmIGMpIHwgKCh+YikgJiBkKSkgKyBtICsgaykgfCAwLCBzKSArIGIpIHwgMFxufVxuXG5mdW5jdGlvbiBmbkcgKGEsIGIsIGMsIGQsIG0sIGssIHMpIHtcbiAgcmV0dXJuIChyb3RsKChhICsgKChiICYgZCkgfCAoYyAmICh+ZCkpKSArIG0gKyBrKSB8IDAsIHMpICsgYikgfCAwXG59XG5cbmZ1bmN0aW9uIGZuSCAoYSwgYiwgYywgZCwgbSwgaywgcykge1xuICByZXR1cm4gKHJvdGwoKGEgKyAoYiBeIGMgXiBkKSArIG0gKyBrKSB8IDAsIHMpICsgYikgfCAwXG59XG5cbmZ1bmN0aW9uIGZuSSAoYSwgYiwgYywgZCwgbSwgaywgcykge1xuICByZXR1cm4gKHJvdGwoKGEgKyAoKGMgXiAoYiB8ICh+ZCkpKSkgKyBtICsgaykgfCAwLCBzKSArIGIpIHwgMFxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IE1ENVxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuZXhwb3J0cy5NYW5hZ2VyID0gZXhwb3J0cy5DaGFpbkNvbmZpZyA9IGV4cG9ydHMuQXBpcyA9IHVuZGVmaW5lZDtcblxudmFyIF9BcGlJbnN0YW5jZXMgPSByZXF1aXJlKCcuL3NyYy9BcGlJbnN0YW5jZXMnKTtcblxudmFyIF9BcGlJbnN0YW5jZXMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfQXBpSW5zdGFuY2VzKTtcblxudmFyIF9Db25uZWN0aW9uTWFuYWdlciA9IHJlcXVpcmUoJy4vc3JjL0Nvbm5lY3Rpb25NYW5hZ2VyJyk7XG5cbnZhciBfQ29ubmVjdGlvbk1hbmFnZXIyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfQ29ubmVjdGlvbk1hbmFnZXIpO1xuXG52YXIgX0NoYWluQ29uZmlnID0gcmVxdWlyZSgnLi9zcmMvQ2hhaW5Db25maWcnKTtcblxudmFyIF9DaGFpbkNvbmZpZzIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9DaGFpbkNvbmZpZyk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmV4cG9ydHMuQXBpcyA9IF9BcGlJbnN0YW5jZXMyLmRlZmF1bHQ7XG5leHBvcnRzLkNoYWluQ29uZmlnID0gX0NoYWluQ29uZmlnMi5kZWZhdWx0O1xuZXhwb3J0cy5NYW5hZ2VyID0gX0Nvbm5lY3Rpb25NYW5hZ2VyMi5kZWZhdWx0OyIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxudmFyIF9DaGFpbldlYlNvY2tldCA9IHJlcXVpcmUoJy4vQ2hhaW5XZWJTb2NrZXQnKTtcblxudmFyIF9DaGFpbldlYlNvY2tldDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9DaGFpbldlYlNvY2tldCk7XG5cbnZhciBfR3JhcGhlbmVBcGkgPSByZXF1aXJlKCcuL0dyYXBoZW5lQXBpJyk7XG5cbnZhciBfR3JhcGhlbmVBcGkyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfR3JhcGhlbmVBcGkpO1xuXG52YXIgX0NoYWluQ29uZmlnID0gcmVxdWlyZSgnLi9DaGFpbkNvbmZpZycpO1xuXG52YXIgX0NoYWluQ29uZmlnMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0NoYWluQ29uZmlnKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIGluc3QgPSB2b2lkIDA7XG5cbnZhciBBcGlzSW5zdGFuY2UgPSBmdW5jdGlvbiAoKSB7XG4gIGZ1bmN0aW9uIEFwaXNJbnN0YW5jZSgpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQXBpc0luc3RhbmNlKTtcbiAgfVxuXG4gIC8qKiBAYXJnIHtzdHJpbmd9IGNvbm5lY3Rpb24gLi4gKi9cbiAgQXBpc0luc3RhbmNlLnByb3RvdHlwZS5jb25uZWN0ID0gZnVuY3Rpb24gY29ubmVjdChjcywgY29ubmVjdFRpbWVvdXQpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gICAgdmFyIHJwY191c2VyID0gJyc7XG4gICAgdmFyIHJwY19wYXNzd29yZCA9ICcnO1xuXG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5sb2NhdGlvbiAmJiB3aW5kb3cubG9jYXRpb24ucHJvdG9jb2wgPT09ICdodHRwczonICYmIGNzLmluZGV4T2YoJ3dzczovLycpIDwgMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdTZWN1cmUgZG9tYWlucyByZXF1aXJlIHdzcyBjb25uZWN0aW9uJyk7XG4gICAgfVxuXG4gICAgdGhpcy53c19ycGMgPSBuZXcgX0NoYWluV2ViU29ja2V0Mi5kZWZhdWx0KGNzLCB0aGlzLnN0YXR1c0NiLCBjb25uZWN0VGltZW91dCk7XG5cbiAgICB0aGlzLmluaXRfcHJvbWlzZSA9IHRoaXMud3NfcnBjLmxvZ2luKHJwY191c2VyLCBycGNfcGFzc3dvcmQpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgY29uc29sZS5sb2coJ0Nvbm5lY3RlZCB0byBBUEkgbm9kZTonLCBjcyk7XG4gICAgICBfdGhpcy5fZGIgPSBuZXcgX0dyYXBoZW5lQXBpMi5kZWZhdWx0KF90aGlzLndzX3JwYywgJ2RhdGFiYXNlJyk7XG4gICAgICBfdGhpcy5fbmV0ID0gbmV3IF9HcmFwaGVuZUFwaTIuZGVmYXVsdChfdGhpcy53c19ycGMsICduZXR3b3JrX2Jyb2FkY2FzdCcpO1xuICAgICAgX3RoaXMuX2hpc3QgPSBuZXcgX0dyYXBoZW5lQXBpMi5kZWZhdWx0KF90aGlzLndzX3JwYywgJ2hpc3RvcnknKTtcbiAgICAgIF90aGlzLl9jcnlwdG8gPSBuZXcgX0dyYXBoZW5lQXBpMi5kZWZhdWx0KF90aGlzLndzX3JwYywgJ2NyeXB0bycpO1xuICAgICAgX3RoaXMuX2Jvb2tpZSA9IG5ldyBfR3JhcGhlbmVBcGkyLmRlZmF1bHQoX3RoaXMud3NfcnBjLCAnYm9va2llJyk7XG4gICAgICB2YXIgZGJfcHJvbWlzZSA9IF90aGlzLl9kYi5pbml0KCkudGhlbihmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBfdGhpcy5fZGIuZXhlYygnZ2V0X2NoYWluX2lkJywgW10pLnRoZW4oZnVuY3Rpb24gKF9jaGFpbl9pZCkge1xuICAgICAgICAgIF90aGlzLmNoYWluX2lkID0gX2NoYWluX2lkO1xuICAgICAgICAgIHJldHVybiBfQ2hhaW5Db25maWcyLmRlZmF1bHQuc2V0Q2hhaW5JZChfY2hhaW5faWQpO1xuICAgICAgICB9KTtcbiAgICAgIH0pO1xuXG4gICAgICBfdGhpcy53c19ycGMub25fcmVjb25uZWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBfdGhpcy53c19ycGMubG9naW4oJycsICcnKS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBfdGhpcy5fZGIuaW5pdCgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKF90aGlzLnN0YXR1c0NiKSB7XG4gICAgICAgICAgICAgIF90aGlzLnN0YXR1c0NiKF9DaGFpbldlYlNvY2tldDIuZGVmYXVsdC5zdGF0dXMuUkVDT05ORUNURUQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pO1xuICAgICAgICAgIF90aGlzLl9uZXQuaW5pdCgpO1xuICAgICAgICAgIF90aGlzLl9oaXN0LmluaXQoKTtcbiAgICAgICAgICBfdGhpcy5fY3J5cHRvLmluaXQoKTtcbiAgICAgICAgICBfdGhpcy5fYm9va2llLmluaXQoKTtcbiAgICAgICAgfSk7XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gUHJvbWlzZS5hbGwoW2RiX3Byb21pc2UsIF90aGlzLl9uZXQuaW5pdCgpLCBfdGhpcy5faGlzdC5pbml0KCksXG4gICAgICAvLyBUZW1wb3Jhcnkgc3F1YXNoIGNyeXB0byBBUEkgZXJyb3IgdW50aWwgdGhlIEFQSSBpcyB1cGdyYWRlZCBldmVyeXdoZXJlXG4gICAgICBfdGhpcy5fY3J5cHRvLmluaXQoKS5jYXRjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICByZXR1cm4gY29uc29sZS5lcnJvcignQXBpSW5zdGFuY2VcXHRDcnlwdG8gQVBJIEVycm9yJywgZSk7XG4gICAgICB9KSwgX3RoaXMuX2Jvb2tpZS5pbml0KCldKTtcbiAgICB9KTtcbiAgfTtcblxuICBBcGlzSW5zdGFuY2UucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gY2xvc2UoKSB7XG4gICAgaWYgKHRoaXMud3NfcnBjKSB7XG4gICAgICB0aGlzLndzX3JwYy5jbG9zZSgpO1xuICAgIH1cblxuICAgIHRoaXMud3NfcnBjID0gbnVsbDtcbiAgfTtcblxuICBBcGlzSW5zdGFuY2UucHJvdG90eXBlLmRiX2FwaSA9IGZ1bmN0aW9uIGRiX2FwaSgpIHtcbiAgICByZXR1cm4gdGhpcy5fZGI7XG4gIH07XG5cbiAgQXBpc0luc3RhbmNlLnByb3RvdHlwZS5uZXR3b3JrX2FwaSA9IGZ1bmN0aW9uIG5ldHdvcmtfYXBpKCkge1xuICAgIHJldHVybiB0aGlzLl9uZXQ7XG4gIH07XG5cbiAgQXBpc0luc3RhbmNlLnByb3RvdHlwZS5oaXN0b3J5X2FwaSA9IGZ1bmN0aW9uIGhpc3RvcnlfYXBpKCkge1xuICAgIHJldHVybiB0aGlzLl9oaXN0O1xuICB9O1xuXG4gIEFwaXNJbnN0YW5jZS5wcm90b3R5cGUuY3J5cHRvX2FwaSA9IGZ1bmN0aW9uIGNyeXB0b19hcGkoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2NyeXB0bztcbiAgfTtcblxuICBBcGlzSW5zdGFuY2UucHJvdG90eXBlLmJvb2tpZV9hcGkgPSBmdW5jdGlvbiBib29raWVfYXBpKCkge1xuICAgIHJldHVybiB0aGlzLl9ib29raWU7XG4gIH07XG5cbiAgQXBpc0luc3RhbmNlLnByb3RvdHlwZS5zZXRScGNDb25uZWN0aW9uU3RhdHVzQ2FsbGJhY2sgPSBmdW5jdGlvbiBzZXRScGNDb25uZWN0aW9uU3RhdHVzQ2FsbGJhY2soY2FsbGJhY2spIHtcbiAgICB0aGlzLnN0YXR1c0NiID0gY2FsbGJhY2s7XG4gIH07XG5cbiAgcmV0dXJuIEFwaXNJbnN0YW5jZTtcbn0oKTtcblxuLyoqXG4gICAgQ29uZmlndXJlOiBjb25maWd1cmUgYXMgZm9sbG93cyBgQXBpcy5pbnN0YW5jZShcIndzOi8vbG9jYWxob3N0OjgwOTBcIikuaW5pdF9wcm9taXNlYC4gIFRoaXNcbiAgICByZXR1cm5zIGEgcHJvbWlzZSwgb25jZSByZXNvbHZlZCB0aGUgY29ubmVjdGlvbiBpcyByZWFkeS5cblxuICAgIEltcG9ydDogaW1wb3J0IHsgQXBpcyB9IGZyb20gXCJAZ3JhcGhlbmUvY2hhaW5cIlxuXG4gICAgU2hvcnQtaGFuZDogQXBpcy5kYihcIm1ldGhvZFwiLCBcInBhcm0xXCIsIDIsIDMsIC4uLikuICBSZXR1cm5zIGEgcHJvbWlzZSB3aXRoIHJlc3VsdHMuXG5cbiAgICBBZGRpdGlvbmFsIHVzYWdlOiBBcGlzLmluc3RhbmNlKCkuZGJfYXBpKCkuZXhlYyhcIm1ldGhvZFwiLCBbXCJtZXRob2RcIiwgXCJwYXJtMVwiLCAyLCAzLCAuLi5dKS5cbiAgICBSZXR1cm5zIGEgcHJvbWlzZSB3aXRoIHJlc3VsdHMuXG4qL1xuXG5leHBvcnRzLmRlZmF1bHQgPSB7XG4gIHNldFJwY0Nvbm5lY3Rpb25TdGF0dXNDYWxsYmFjazogZnVuY3Rpb24gc2V0UnBjQ29ubmVjdGlvblN0YXR1c0NhbGxiYWNrKGNhbGxiYWNrKSB7XG4gICAgdGhpcy5zdGF0dXNDYiA9IGNhbGxiYWNrO1xuXG4gICAgaWYgKGluc3QpIHtcbiAgICAgIGluc3Quc2V0UnBjQ29ubmVjdGlvblN0YXR1c0NhbGxiYWNrKGNhbGxiYWNrKTtcbiAgICB9XG4gIH0sXG5cbiAgLyoqXG4gICAgICAgIEBhcmcge3N0cmluZ30gY3MgaXMgb25seSBwcm92aWRlZCBpbiB0aGUgZmlyc3QgY2FsbFxuICAgICAgICBAcmV0dXJuIHtBcGlzfSBzaW5nbGV0b24gLi4gQ2hlY2sgQXBpcy5pbnN0YW5jZSgpLmluaXRfcHJvbWlzZSB0b1xuICAgICAgICBrbm93IHdoZW4gdGhlIGNvbm5lY3Rpb24gaXMgZXN0YWJsaXNoZWRcbiAgICAqL1xuICByZXNldDogZnVuY3Rpb24gcmVzZXQoKSB7XG4gICAgdmFyIGNzID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiAnd3M6Ly9sb2NhbGhvc3Q6ODA5MCc7XG4gICAgdmFyIGNvbm5lY3QgPSBhcmd1bWVudHNbMV07XG4gICAgdmFyIGNvbm5lY3RUaW1lb3V0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDIgJiYgYXJndW1lbnRzWzJdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMl0gOiA0MDAwO1xuXG4gICAgaWYgKGluc3QpIHtcbiAgICAgIGluc3QuY2xvc2UoKTtcbiAgICAgIGluc3QgPSBudWxsO1xuICAgIH1cblxuICAgIGluc3QgPSBuZXcgQXBpc0luc3RhbmNlKCk7XG4gICAgaW5zdC5zZXRScGNDb25uZWN0aW9uU3RhdHVzQ2FsbGJhY2sodGhpcy5zdGF0dXNDYik7XG5cbiAgICBpZiAoaW5zdCAmJiBjb25uZWN0KSB7XG4gICAgICBpbnN0LmNvbm5lY3QoY3MsIGNvbm5lY3RUaW1lb3V0KTtcbiAgICB9XG5cbiAgICByZXR1cm4gaW5zdDtcbiAgfSxcbiAgaW5zdGFuY2U6IGZ1bmN0aW9uIGluc3RhbmNlKCkge1xuICAgIHZhciBjcyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDogJ3dzOi8vbG9jYWxob3N0OjgwOTAnO1xuICAgIHZhciBjb25uZWN0ID0gYXJndW1lbnRzWzFdO1xuICAgIHZhciBjb25uZWN0VGltZW91dCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogNDAwMDtcblxuICAgIGlmICghaW5zdCkge1xuICAgICAgaW5zdCA9IG5ldyBBcGlzSW5zdGFuY2UoKTtcbiAgICAgIGluc3Quc2V0UnBjQ29ubmVjdGlvblN0YXR1c0NhbGxiYWNrKHRoaXMuc3RhdHVzQ2IpO1xuICAgIH1cblxuICAgIGlmIChpbnN0ICYmIGNvbm5lY3QpIHtcbiAgICAgIGluc3QuY29ubmVjdChjcywgY29ubmVjdFRpbWVvdXQpO1xuICAgIH1cblxuICAgIHJldHVybiBpbnN0O1xuICB9LFxuICBjaGFpbklkOiBmdW5jdGlvbiBjaGFpbklkKCkge1xuICAgIHJldHVybiB0aGlzLmluc3RhbmNlKCkuY2hhaW5faWQ7XG4gIH0sXG4gIGNsb3NlOiBmdW5jdGlvbiBjbG9zZSgpIHtcbiAgICBpZiAoaW5zdCkge1xuICAgICAgaW5zdC5jbG9zZSgpO1xuICAgICAgaW5zdCA9IG51bGw7XG4gICAgfVxuICB9XG4gIC8vIGRiOiAobWV0aG9kLCAuLi5hcmdzKSA9PiBBcGlzLmluc3RhbmNlKCkuZGJfYXBpKCkuZXhlYyhtZXRob2QsIHRvU3RyaW5ncyhhcmdzKSksXG4gIC8vIG5ldHdvcms6IChtZXRob2QsIC4uLmFyZ3MpID0+IEFwaXMuaW5zdGFuY2UoKS5uZXR3b3JrX2FwaSgpLmV4ZWMobWV0aG9kLCB0b1N0cmluZ3MoYXJncykpLFxuICAvLyBoaXN0b3J5OiAobWV0aG9kLCAuLi5hcmdzKSA9PiBBcGlzLmluc3RhbmNlKCkuaGlzdG9yeV9hcGkoKS5leGVjKG1ldGhvZCwgdG9TdHJpbmdzKGFyZ3MpKSxcbiAgLy8gY3J5cHRvOiAobWV0aG9kLCAuLi5hcmdzKSA9PiBBcGlzLmluc3RhbmNlKCkuY3J5cHRvX2FwaSgpLmV4ZWMobWV0aG9kLCB0b1N0cmluZ3MoYXJncykpXG5cbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG52YXIgZGVmYXVsdHMgPSB7XG4gIGNvcmVfYXNzZXQ6ICdQUFknLFxuICBhZGRyZXNzX3ByZWZpeDogJ1BQWScsXG4gIGV4cGlyZV9pbl9zZWNzOiAxNSxcbiAgZXhwaXJlX2luX3NlY3NfcHJvcG9zYWw6IDI0ICogNjAgKiA2MCxcbiAgcmV2aWV3X2luX3NlY3NfY29tbWl0dGVlOiAyNCAqIDYwICogNjBcbn07XG5cbnZhciBuZXR3b3JrcyA9IHtcbiAgbmV0d29ya3M6IHtcbiAgICBQZWVycGxheXM6IHtcbiAgICAgIGNvcmVfYXNzZXQ6ICdQUFknLFxuICAgICAgYWRkcmVzc19wcmVmaXg6ICdQUFknLFxuICAgICAgY2hhaW5faWQ6ICc2YjZiNWYwY2U3YTM2ZDMyMzc2OGU1MzRmM2VkYjQxYzZkNjMzMmE1NDFhOTU3MjViOThlMjhkMTQwODUwMTM0J1xuICAgIH0sXG4gICAgUGVlcnBsYXlzVGVzdG5ldDoge1xuICAgICAgY29yZV9hc3NldDogJ1BQWVRFU1QnLFxuICAgICAgYWRkcmVzc19wcmVmaXg6ICdQUFlURVNUJyxcbiAgICAgIGNoYWluX2lkOiAnYmU2Yjc5Mjk1ZTcyODQwNmNiYjc0OTRiY2I2MjZlNjJhZDI3OGZhNDAxODY5OWNmOGY3NTczOWY0YzFhODFmZCdcbiAgICB9XG4gIH1cbn07XG5cbnZhciBDaGFpbkNvbmZpZyA9IGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gQ2hhaW5Db25maWcoKSB7XG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIENoYWluQ29uZmlnKTtcblxuICAgIHRoaXMucmVzZXQoKTtcbiAgfVxuXG4gIENoYWluQ29uZmlnLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uIHJlc2V0KCkge1xuICAgIE9iamVjdC5hc3NpZ24odGhpcywgZGVmYXVsdHMpO1xuICB9O1xuXG4gIENoYWluQ29uZmlnLnByb3RvdHlwZS5zZXRDaGFpbklkID0gZnVuY3Rpb24gc2V0Q2hhaW5JZChjaGFpbklEKSB7XG4gICAgdmFyIHJlZiA9IE9iamVjdC5rZXlzKG5ldHdvcmtzKTtcblxuICAgIGZvciAodmFyIGkgPSAwLCBsZW4gPSByZWYubGVuZ3RoOyBpIDwgbGVuOyBpKyspIHtcbiAgICAgIHZhciBuZXR3b3JrX25hbWUgPSByZWZbaV07XG4gICAgICB2YXIgbmV0d29yayA9IG5ldHdvcmtzW25ldHdvcmtfbmFtZV07XG5cbiAgICAgIGlmIChuZXR3b3JrLmNoYWluX2lkID09PSBjaGFpbklEKSB7XG4gICAgICAgIHRoaXMubmV0d29ya19uYW1lID0gbmV0d29ya19uYW1lO1xuXG4gICAgICAgIGlmIChuZXR3b3JrLmFkZHJlc3NfcHJlZml4KSB7XG4gICAgICAgICAgdGhpcy5hZGRyZXNzX3ByZWZpeCA9IG5ldHdvcmsuYWRkcmVzc19wcmVmaXg7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIG5ldHdvcmtfbmFtZTogbmV0d29ya19uYW1lLFxuICAgICAgICAgIG5ldHdvcms6IG5ldHdvcmtcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMubmV0d29ya19uYW1lKSB7XG4gICAgICBjb25zb2xlLmxvZygnVW5rbm93biBjaGFpbiBpZCAodGhpcyBtYXkgYmUgYSB0ZXN0bmV0KScsIGNoYWluSUQpO1xuICAgIH1cbiAgfTtcblxuICBDaGFpbkNvbmZpZy5wcm90b3R5cGUuc2V0UHJlZml4ID0gZnVuY3Rpb24gc2V0UHJlZml4KCkge1xuICAgIHZhciBwcmVmaXggPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6ICdQUFknO1xuXG4gICAgdGhpcy5hZGRyZXNzX3ByZWZpeCA9IHByZWZpeDtcbiAgfTtcblxuICByZXR1cm4gQ2hhaW5Db25maWc7XG59KCk7XG5cbmV4cG9ydHMuZGVmYXVsdCA9IG5ldyBDaGFpbkNvbmZpZygpOyIsIid1c2Ugc3RyaWN0JztcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZnVuY3Rpb24gX2NsYXNzQ2FsbENoZWNrKGluc3RhbmNlLCBDb25zdHJ1Y3RvcikgeyBpZiAoIShpbnN0YW5jZSBpbnN0YW5jZW9mIENvbnN0cnVjdG9yKSkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IGNhbGwgYSBjbGFzcyBhcyBhIGZ1bmN0aW9uXCIpOyB9IH1cblxudmFyIFNPQ0tFVF9ERUJVRyA9IGZhbHNlO1xudmFyIFdlYlNvY2tldENsaWVudCA9IG51bGw7XG5cbmlmICh0eXBlb2YgV2ViU29ja2V0ICE9PSAndW5kZWZpbmVkJykge1xuICBXZWJTb2NrZXRDbGllbnQgPSBXZWJTb2NrZXQ7XG59IGVsc2Uge1xuICBXZWJTb2NrZXRDbGllbnQgPSByZXF1aXJlKCd3cycpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lIGdsb2JhbC1yZXF1aXJlXG59XG5cbnZhciBTVUJTQ1JJQkVfT1BFUkFUSU9OUyA9IFsnc2V0X3N1YnNjcmliZV9jYWxsYmFjaycsICdzdWJzY3JpYmVfdG9fbWFya2V0JywgJ2Jyb2FkY2FzdF90cmFuc2FjdGlvbl93aXRoX2NhbGxiYWNrJywgJ3NldF9wZW5kaW5nX3RyYW5zYWN0aW9uX2NhbGxiYWNrJ107XG5cbnZhciBVTlNVQlNDUklCRV9PUEVSQVRJT05TID0gWyd1bnN1YnNjcmliZV9mcm9tX21hcmtldCcsICd1bnN1YnNjcmliZV9mcm9tX2FjY291bnRzJ107XG5cbnZhciBIRUFMVEhfQ0hFQ0tfSU5URVJWQUwgPSAxMDAwMDtcblxudmFyIENoYWluV2ViU29ja2V0ID0gZnVuY3Rpb24gKCkge1xuICAvKipcbiAgICpDcmVhdGVzIGFuIGluc3RhbmNlIG9mIENoYWluV2ViU29ja2V0LlxuICAgKiBAcGFyYW0ge3N0cmluZ30gICAgc2VydmVyQWRkcmVzcyAgICAgICAgICAgVGhlIGFkZHJlc3Mgb2YgdGhlIHdlYnNvY2tldCB0byBjb25uZWN0IHRvLlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSAgc3RhdHVzQ2IgICAgICAgICAgICAgICAgQ2FsbGVkIHdoZW4gc3RhdHVzIGV2ZW50cyBvY2N1ci5cbiAgICogQHBhcmFtIHtudW1iZXJ9ICAgIFtjb25uZWN0VGltZW91dD0xMDAwMF0gIFRoZSB0aW1lIGZvciBhIGNvbm5lY3Rpb24gYXR0ZW1wdCB0byBjb21wbGV0ZS5cbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuICBmdW5jdGlvbiBDaGFpbldlYlNvY2tldChzZXJ2ZXJBZGRyZXNzLCBzdGF0dXNDYikge1xuICAgIHZhciBjb25uZWN0VGltZW91dCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogMTAwMDA7XG5cbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQ2hhaW5XZWJTb2NrZXQpO1xuXG4gICAgdGhpcy5zdGF0dXNDYiA9IHN0YXR1c0NiO1xuICAgIHRoaXMuc2VydmVyQWRkcmVzcyA9IHNlcnZlckFkZHJlc3M7XG4gICAgdGhpcy50aW1lb3V0SW50ZXJ2YWwgPSBjb25uZWN0VGltZW91dDtcblxuICAgIC8vIFRoZSBjdXJyZW5jdCBjb25uZWN0aW9uIHN0YXRlIG9mIHRoZSB3ZWJzb2NrZXQuXG4gICAgdGhpcy5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgICB0aGlzLnJlY29ubmVjdFRpbWVvdXQgPSBudWxsO1xuXG4gICAgLy8gQ2FsbGJhY2sgdG8gZXhlY3V0ZSB3aGVuIHRoZSB3ZWJzb2NrZXQgaXMgcmVjb25uZWN0ZWQuXG4gICAgdGhpcy5vbl9yZWNvbm5lY3QgPSBudWxsO1xuXG4gICAgLy8gQW4gaW5jcmVtZW50aW5nIElEIGZvciBlYWNoIHJlcXVlc3Qgc28gdGhhdCB3ZSBjYW4gcGFpciBpdCB3aXRoIHRoZVxuICAgIC8vIHJlc3BvbnNlIGZyb20gdGhlIHdlYnNvY2tldC5cbiAgICB0aGlzLmNiSWQgPSAwO1xuXG4gICAgLy8gT2JqZWN0cyB0byBzdG9yZSBrZXkvdmFsdWUgcGFpcnMgZm9yIGNhbGxiYWNrcywgc3Vic2NyaXB0aW9uIGNhbGxiYWNrc1xuICAgIC8vIGFuZCB1bnN1YnNjcmliZSBjYWxsYmFja3MuXG4gICAgdGhpcy5jYnMgPSB7fTtcbiAgICB0aGlzLnN1YnMgPSB7fTtcbiAgICB0aGlzLnVuc3ViID0ge307XG5cbiAgICAvLyBDdXJyZW50IGNvbm5lY3Rpb24gcHJvbWlzZXMnIHJlamVjdGlvblxuICAgIHRoaXMuY3VycmVudFJlc29sdmUgPSBudWxsO1xuICAgIHRoaXMuY3VycmVudFJlamVjdCA9IG51bGw7XG5cbiAgICAvLyBIZWFsdGggY2hlY2sgZm9yIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBCbG9ja0NoYWluLlxuICAgIHRoaXMuaGVhbHRoQ2hlY2sgPSBudWxsO1xuXG4gICAgLy8gQ29weSB0aGUgY29uc3RhbnRzIHRvIHRoaXMgaW5zdGFuY2UuXG4gICAgdGhpcy5zdGF0dXMgPSBDaGFpbldlYlNvY2tldC5zdGF0dXM7XG5cbiAgICAvLyBCaW5kIHRoZSBmdW5jdGlvbnMgdG8gdGhlIGluc3RhbmNlLlxuICAgIHRoaXMub25Db25uZWN0aW9uT3BlbiA9IHRoaXMub25Db25uZWN0aW9uT3Blbi5iaW5kKHRoaXMpO1xuICAgIHRoaXMub25Db25uZWN0aW9uQ2xvc2UgPSB0aGlzLm9uQ29ubmVjdGlvbkNsb3NlLmJpbmQodGhpcyk7XG4gICAgdGhpcy5vbkNvbm5lY3Rpb25UZXJtaW5hdGUgPSB0aGlzLm9uQ29ubmVjdGlvblRlcm1pbmF0ZS5iaW5kKHRoaXMpO1xuICAgIHRoaXMub25Db25uZWN0aW9uRXJyb3IgPSB0aGlzLm9uQ29ubmVjdGlvbkVycm9yLmJpbmQodGhpcyk7XG4gICAgdGhpcy5vbkNvbm5lY3Rpb25UaW1lb3V0ID0gdGhpcy5vbkNvbm5lY3Rpb25UaW1lb3V0LmJpbmQodGhpcyk7XG4gICAgdGhpcy5jcmVhdGVDb25uZWN0aW9uID0gdGhpcy5jcmVhdGVDb25uZWN0aW9uLmJpbmQodGhpcyk7XG4gICAgdGhpcy5jcmVhdGVDb25uZWN0aW9uUHJvbWlzZSA9IHRoaXMuY3JlYXRlQ29ubmVjdGlvblByb21pc2UuYmluZCh0aGlzKTtcbiAgICB0aGlzLmxpc3RlbmVyID0gdGhpcy5saXN0ZW5lci5iaW5kKHRoaXMpO1xuXG4gICAgLy8gQ3JlYXRlIHRoZSBpbml0aWFsIGNvbm5lY3Rpb24gdGhlIGJsb2NrY2hhaW4uXG4gICAgdGhpcy5jcmVhdGVDb25uZWN0aW9uKCk7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIHRoZSBjb25uZWN0aW9uIHRvIHRoZSBCbG9ja2NoYWluLlxuICAgKlxuICAgKiBAcmV0dXJuc1xuICAgKiBAbWVtYmVyb2YgQ2hhaW5XZWJTb2NrZXRcbiAgICovXG5cblxuICBDaGFpbldlYlNvY2tldC5wcm90b3R5cGUuY3JlYXRlQ29ubmVjdGlvbiA9IGZ1bmN0aW9uIGNyZWF0ZUNvbm5lY3Rpb24oKSB7XG4gICAgdGhpcy5kZWJ1ZygnISEhIENoYWluV2ViU29ja2V0IGNyZWF0ZSBjb25uZWN0aW9uJyk7XG5cbiAgICAvLyBDbGVhciBhbnkgcG9zc2libGUgcmVjb25uZWN0IHRpbWVycy5cbiAgICB0aGlzLnJlY29ubmVjdFRpbWVvdXQgPSBudWxsO1xuXG4gICAgLy8gQ3JlYXRlIHRoZSBwcm9taXNlIGZvciB0aGlzIGNvbm5lY3Rpb25cbiAgICBpZiAoIXRoaXMuY29ubmVjdF9wcm9taXNlKSB7XG4gICAgICB0aGlzLmNvbm5lY3RfcHJvbWlzZSA9IG5ldyBQcm9taXNlKHRoaXMuY3JlYXRlQ29ubmVjdGlvblByb21pc2UpO1xuICAgIH1cblxuICAgIC8vIEF0dGVtcHQgdG8gY3JlYXRlIHRoZSB3ZWJzb2NrZXRcbiAgICB0cnkge1xuICAgICAgdGhpcy53cyA9IG5ldyBXZWJTb2NrZXRDbGllbnQodGhpcy5zZXJ2ZXJBZGRyZXNzKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgLy8gU2V0IGEgdGltZW91dCB0byB0cnkgYW5kIHJlY29ubmVjdCBoZXJlLlxuICAgICAgcmV0dXJuIHRoaXMucmVzZXRDb25uZWN0aW9uKCk7XG4gICAgfVxuXG4gICAgdGhpcy5hZGRFdmVudExpc3RlbmVycygpO1xuXG4gICAgLy8gSGFuZGxlIHRpbWVvdXRzIHRvIHRoZSB3ZWJzb2NrZXQncyBpbml0aWFsIGNvbm5lY3Rpb24uXG4gICAgdGhpcy5jb25uZWN0aW9uVGltZW91dCA9IHNldFRpbWVvdXQodGhpcy5vbkNvbm5lY3Rpb25UaW1lb3V0LCB0aGlzLnRpbWVvdXRJbnRlcnZhbCk7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRoZSBjb25uZWN0aW9uIHRvIHRoZSBCbG9ja0NoYWluLlxuICAgKlxuICAgKiBAbWVtYmVyb2YgQ2hhaW5XZWJTb2NrZXRcbiAgICovXG5cblxuICBDaGFpbldlYlNvY2tldC5wcm90b3R5cGUucmVzZXRDb25uZWN0aW9uID0gZnVuY3Rpb24gcmVzZXRDb25uZWN0aW9uKCkge1xuICAgIC8vIENsb3NlIHRoZSBXZWJzb2NrZXQgaWYgaXRzIHN0aWxsICdoYWxmLW9wZW4nXG4gICAgdGhpcy5jbG9zZSgpO1xuXG4gICAgLy8gTWFrZSBzdXJlIHdlIG9ubHkgZXZlciBoYXZlIG9uZSB0aW1lb3V0IHJ1bm5pbmcgdG8gcmVjb25uZWN0LlxuICAgIGlmICghdGhpcy5yZWNvbm5lY3RUaW1lb3V0KSB7XG4gICAgICB0aGlzLmRlYnVnKCchISEgQ2hhaW5XZWJTb2NrZXQgcmVzZXQgY29ubmVjdGlvbicsIHRoaXMudGltZW91dEludGVydmFsKTtcbiAgICAgIHRoaXMucmVjb25uZWN0VGltZW91dCA9IHNldFRpbWVvdXQodGhpcy5jcmVhdGVDb25uZWN0aW9uLCB0aGlzLnRpbWVvdXRJbnRlcnZhbCk7XG4gICAgfVxuXG4gICAgLy8gUmVqZWN0IHRoZSBjdXJyZW50IHByb21pc2UgaWYgdGhlcmUgaXMgb25lLlxuICAgIGlmICh0aGlzLmN1cnJlbnRSZWplY3QpIHtcbiAgICAgIHRoaXMuY3VycmVudFJlamVjdChuZXcgRXJyb3IoJ0Nvbm5lY3Rpb24gYXR0ZW1wdCBmYWlsZWQ6ICcgKyB0aGlzLnNlcnZlckFkZHJlc3MpKTtcbiAgICB9XG4gIH07XG5cbiAgLyoqXG4gICAqIEFkZCBldmVudCBsaXN0ZW5lcnMgdG8gdGhlIFdlYlNvY2tldC5cbiAgICpcbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuXG5cbiAgQ2hhaW5XZWJTb2NrZXQucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXJzID0gZnVuY3Rpb24gYWRkRXZlbnRMaXN0ZW5lcnMoKSB7XG4gICAgdGhpcy5kZWJ1ZygnISEhIENoYWluV2ViU29ja2V0IGFkZCBldmVudCBsaXN0ZW5lcnMnKTtcbiAgICB0aGlzLndzLmFkZEV2ZW50TGlzdGVuZXIoJ29wZW4nLCB0aGlzLm9uQ29ubmVjdGlvbk9wZW4pO1xuICAgIHRoaXMud3MuYWRkRXZlbnRMaXN0ZW5lcignY2xvc2UnLCB0aGlzLm9uQ29ubmVjdGlvbkNsb3NlKTtcbiAgICB0aGlzLndzLmFkZEV2ZW50TGlzdGVuZXIoJ2Vycm9yJywgdGhpcy5vbkNvbm5lY3Rpb25FcnJvcik7XG4gICAgdGhpcy53cy5hZGRFdmVudExpc3RlbmVyKCdtZXNzYWdlJywgdGhpcy5saXN0ZW5lcik7XG4gIH07XG5cbiAgLyoqXG4gICAqIFJlbW92ZSB0aGUgZXZlbnQgbGlzdGVycyBmcm9tIHRoZSBXZWJTb2NrZXQuIEl0cyBpbXBvcnRhbnQgdG8gcmVtb3ZlIHRoZSBldmVudCBsaXN0ZXJlcnNcbiAgICogZm9yIGdhcmJhYWdlIGNvbGxlY3Rpb24uIEJlY2F1c2Ugd2UgYXJlIGNyZWF0aW5nIGEgbmV3IFdlYlNvY2tldCBvbiBlYWNoIGNvbm5lY3Rpb24gYXR0ZW1wdFxuICAgKiBhbnkgbGlzdGVuZXJzIHRoYXQgYXJlIHN0aWxsIGF0dGFjaGVkIGNvdWxkIHByZXZlbnQgdGhlIG9sZCBzb2NrZXRzIGZyb21cbiAgICogYmVpbmcgZ2FyYmFnZSBjb2xsZWN0ZWQuXG4gICAqXG4gICAqIEBtZW1iZXJvZiBDaGFpbldlYlNvY2tldFxuICAgKi9cblxuXG4gIENoYWluV2ViU29ja2V0LnByb3RvdHlwZS5yZW1vdmVFdmVudExpc3RlbmVycyA9IGZ1bmN0aW9uIHJlbW92ZUV2ZW50TGlzdGVuZXJzKCkge1xuICAgIHRoaXMuZGVidWcoJyEhISBDaGFpbldlYlNvY2tldCByZW1vdmUgZXZlbnQgbGlzdGVuZXJzJyk7XG4gICAgdGhpcy53cy5yZW1vdmVFdmVudExpc3RlbmVyKCdvcGVuJywgdGhpcy5vbkNvbm5lY3Rpb25PcGVuKTtcbiAgICB0aGlzLndzLnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Nsb3NlJywgdGhpcy5vbkNvbm5lY3Rpb25DbG9zZSk7XG4gICAgdGhpcy53cy5yZW1vdmVFdmVudExpc3RlbmVyKCdlcnJvcicsIHRoaXMub25Db25uZWN0aW9uRXJyb3IpO1xuICAgIHRoaXMud3MucmVtb3ZlRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRoaXMubGlzdGVuZXIpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBBIGZ1bmN0aW9uIHRoYXQgaXMgcGFzc2VkIHRvIGEgbmV3IHByb21pc2UgdGhhdCBzdG9yZXMgdGhlIHJlc29sdmUgYW5kIHJlamVjdCBjYWxsYmFja3NcbiAgICogaW4gdGhlIHN0YXRlLlxuICAgKlxuICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSByZXNvbHZlIEEgY2FsbGJhY2sgdG8gYmUgZXhlY3V0ZWQgd2hlbiB0aGUgcHJvbWlzZSBpcyByZXNvbHZlZC5cbiAgICogQHBhcmFtIHtmdW5jdGlvbn0gcmVqZWN0IEEgY2FsbGJhY2sgdG8gYmUgZXhlY3V0ZWQgd2hlbiB0aGUgcHJvbWlzZSBpcyByZWplY3RlZC5cbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuXG5cbiAgQ2hhaW5XZWJTb2NrZXQucHJvdG90eXBlLmNyZWF0ZUNvbm5lY3Rpb25Qcm9taXNlID0gZnVuY3Rpb24gY3JlYXRlQ29ubmVjdGlvblByb21pc2UocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdGhpcy5kZWJ1ZygnISEhIENoYWluV2ViU29ja2V0IGNyZWF0ZVByb21pc2UnKTtcbiAgICB0aGlzLmN1cnJlbnRSZXNvbHZlID0gcmVzb2x2ZTtcbiAgICB0aGlzLmN1cnJlbnRSZWplY3QgPSByZWplY3Q7XG4gIH07XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIGEgbmV3IFdlYnNvY2tldCBjb25uZWN0aW9uIGlzIG9wZW5lZC5cbiAgICpcbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuXG5cbiAgQ2hhaW5XZWJTb2NrZXQucHJvdG90eXBlLm9uQ29ubmVjdGlvbk9wZW4gPSBmdW5jdGlvbiBvbkNvbm5lY3Rpb25PcGVuKCkge1xuICAgIHRoaXMuZGVidWcoJyEhISBDaGFpbldlYlNvY2tldCBDb25uZWN0ZWQgJyk7XG5cbiAgICB0aGlzLmNvbm5lY3RlZCA9IHRydWU7XG5cbiAgICBjbGVhclRpbWVvdXQodGhpcy5jb25uZWN0aW9uVGltZW91dCk7XG4gICAgdGhpcy5jb25uZWN0aW9uVGltZW91dCA9IG51bGw7XG5cbiAgICAvLyBUaGlzIHdpbGwgdHJpZ2dlciB0aGUgbG9naW4gcHJvY2VzcyBhcyB3ZWxsIGFzIHNvbWUgYWRkaXRpb25hbCBzZXR1cCBpbiBBcGlJbnN0YW5jZXNcbiAgICBpZiAodGhpcy5vbl9yZWNvbm5lY3QpIHtcbiAgICAgIHRoaXMub25fcmVjb25uZWN0KCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY3VycmVudFJlc29sdmUpIHtcbiAgICAgIHRoaXMuY3VycmVudFJlc29sdmUoKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zdGF0dXNDYikge1xuICAgICAgdGhpcy5zdGF0dXNDYihDaGFpbldlYlNvY2tldC5zdGF0dXMuT1BFTik7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBjYWxsZWQgd2hlbiB0aGUgY29ubmVjdGlvbiBhdHRlbXB0IHRpbWVzIG91dC5cbiAgICpcbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuXG5cbiAgQ2hhaW5XZWJTb2NrZXQucHJvdG90eXBlLm9uQ29ubmVjdGlvblRpbWVvdXQgPSBmdW5jdGlvbiBvbkNvbm5lY3Rpb25UaW1lb3V0KCkge1xuICAgIHRoaXMuZGVidWcoJyEhISBDaGFpbldlYlNvY2tldCB0aW1lb3V0Jyk7XG4gICAgdGhpcy5vbkNvbm5lY3Rpb25DbG9zZShuZXcgRXJyb3IoJ0Nvbm5lY3Rpb24gdGltZWQgb3V0LicpKTtcbiAgfTtcblxuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gdGhlIFdlYnNvY2tldCBpcyBub3QgcmVzcG9uZGluZyB0byB0aGUgaGVhbHRoIGNoZWNrcy5cbiAgICpcbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuXG5cbiAgQ2hhaW5XZWJTb2NrZXQucHJvdG90eXBlLm9uQ29ubmVjdGlvblRlcm1pbmF0ZSA9IGZ1bmN0aW9uIG9uQ29ubmVjdGlvblRlcm1pbmF0ZSgpIHtcbiAgICB0aGlzLmRlYnVnKCchISEgQ2hhaW5XZWJTb2NrZXQgdGVybWluYXRlJyk7XG4gICAgdGhpcy5vbkNvbm5lY3Rpb25DbG9zZShuZXcgRXJyb3IoJ0Nvbm5lY3Rpb24gd2FzIHRlcm1pbmF0ZWQuJykpO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDYWxsZWQgd2hlbiB0aGUgY29ubmVjdGlvbiB0byB0aGUgQmxvY2tjaGFpbiBpcyBjbG9zZWQuXG4gICAqXG4gICAqIEBwYXJhbSB7Kn0gZXJyb3JcbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuXG5cbiAgQ2hhaW5XZWJTb2NrZXQucHJvdG90eXBlLm9uQ29ubmVjdGlvbkNsb3NlID0gZnVuY3Rpb24gb25Db25uZWN0aW9uQ2xvc2UoZXJyb3IpIHtcbiAgICB0aGlzLmRlYnVnKCchISEgQ2hhaW5XZWJTb2NrZXQgQ2xvc2UgJywgZXJyb3IpO1xuXG4gICAgdGhpcy5yZXNldENvbm5lY3Rpb24oKTtcblxuICAgIGlmICh0aGlzLnN0YXR1c0NiKSB7XG4gICAgICB0aGlzLnN0YXR1c0NiKENoYWluV2ViU29ja2V0LnN0YXR1cy5DTE9TRUQpO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogQ2FsbGVkIHdoZW4gdGhlIFdlYnNvY2tldCBlbmNvdW50ZXJzIGFuIGVycm9yLlxuICAgKlxuICAgKiBAcGFyYW0geyp9IGVycm9yXG4gICAqIEBtZW1iZXJvZiBDaGFpbldlYlNvY2tldFxuICAgKi9cblxuXG4gIENoYWluV2ViU29ja2V0LnByb3RvdHlwZS5vbkNvbm5lY3Rpb25FcnJvciA9IGZ1bmN0aW9uIG9uQ29ubmVjdGlvbkVycm9yKGVycm9yKSB7XG4gICAgdGhpcy5kZWJ1ZygnISEhIENoYWluV2ViU29ja2V0IE9uIENvbm5lY3Rpb24gRXJyb3IgJywgZXJyb3IpO1xuXG4gICAgdGhpcy5yZXNldENvbm5lY3Rpb24oKTtcblxuICAgIGlmICh0aGlzLnN0YXR1c0NiKSB7XG4gICAgICB0aGlzLnN0YXR1c0NiKENoYWluV2ViU29ja2V0LnN0YXR1cy5FUlJPUik7XG4gICAgfVxuICB9O1xuXG4gIC8qKlxuICAgKiBFbnRyeSBwb2ludCB0byBtYWtlIFJQQyBjYWxscyBvbiB0aGUgQmxvY2tDaGFpbi5cbiAgICpcbiAgICogQHBhcmFtIHthcnJheX0gcGFyYW1zIEFuIGFycmF5IG9mIHBhcmFtcyB0byBiZSBwYXNzZWQgdG8gdGhlIHJwYyBjYWxsLiBbbWV0aG9kLCAuLi5wYXJhbXNdXG4gICAqIEByZXR1cm5zIEEgbmV3IHByb21pc2UgZm9yIHRoaXMgc3BlY2lmaWMgY2FsbC5cbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuXG5cbiAgQ2hhaW5XZWJTb2NrZXQucHJvdG90eXBlLmNhbGwgPSBmdW5jdGlvbiBjYWxsKHBhcmFtcykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICBpZiAoIXRoaXMuY29ubmVjdGVkKSB7XG4gICAgICB0aGlzLmRlYnVnKCchISEgQ2hhaW5XZWJTb2NrZXQgQ2FsbCBub3QgY29ubmVjdGVkLiAnKTtcbiAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChuZXcgRXJyb3IoJ0Rpc2Nvbm5lY3RlZCBmcm9tIHRoZSBCbG9ja0NoYWluLicpKTtcbiAgICB9XG5cbiAgICB0aGlzLmRlYnVnKCchISEgQ2hhaW5XZWJTb2NrZXQgQ2FsbCBjb25uZWN0ZWQuICcsIHBhcmFtcyk7XG5cbiAgICB2YXIgcmVxdWVzdCA9IHtcbiAgICAgIG1ldGhvZDogcGFyYW1zWzFdLFxuICAgICAgcGFyYW1zOiBwYXJhbXMsXG4gICAgICBpZDogdGhpcy5jYklkICsgMVxuICAgIH07XG5cbiAgICB0aGlzLmNiSWQgPSByZXF1ZXN0LmlkO1xuXG4gICAgaWYgKFNVQlNDUklCRV9PUEVSQVRJT05TLmluY2x1ZGVzKHJlcXVlc3QubWV0aG9kKSkge1xuICAgICAgLy8gU3RvcmUgY2FsbGJhY2sgaW4gc3VicyBtYXBcbiAgICAgIHRoaXMuc3Vic1tyZXF1ZXN0LmlkXSA9IHtcbiAgICAgICAgY2FsbGJhY2s6IHJlcXVlc3QucGFyYW1zWzJdWzBdXG4gICAgICB9O1xuXG4gICAgICAvLyBSZXBsYWNlIGNhbGxiYWNrIHdpdGggdGhlIGNhbGxiYWNrIGlkXG4gICAgICByZXF1ZXN0LnBhcmFtc1syXVswXSA9IHJlcXVlc3QuaWQ7XG4gICAgfVxuXG4gICAgaWYgKFVOU1VCU0NSSUJFX09QRVJBVElPTlMuaW5jbHVkZXMocmVxdWVzdC5tZXRob2QpKSB7XG4gICAgICBpZiAodHlwZW9mIHJlcXVlc3QucGFyYW1zWzJdWzBdICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmlyc3QgcGFyYW1ldGVyIG9mIHVuc3ViIG11c3QgYmUgdGhlIG9yaWdpbmFsIGNhbGxiYWNrJyk7XG4gICAgICB9XG5cbiAgICAgIHZhciB1blN1YkNiID0gcmVxdWVzdC5wYXJhbXNbMl0uc3BsaWNlKDAsIDEpWzBdO1xuXG4gICAgICAvLyBGaW5kIHRoZSBjb3JyZXNwb25kaW5nIHN1YnNjcmlwdGlvblxuICAgICAgZm9yICh2YXIgaWQgaW4gdGhpcy5zdWJzKSB7XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmVcbiAgICAgICAgaWYgKHRoaXMuc3Vic1tpZF0uY2FsbGJhY2sgPT09IHVuU3ViQ2IpIHtcbiAgICAgICAgICB0aGlzLnVuc3ViW3JlcXVlc3QuaWRdID0gaWQ7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaGVhbHRoQ2hlY2spIHtcbiAgICAgIHRoaXMuaGVhbHRoQ2hlY2sgPSBzZXRUaW1lb3V0KHRoaXMub25Db25uZWN0aW9uVGVybWluYXRlLmJpbmQodGhpcyksIEhFQUxUSF9DSEVDS19JTlRFUlZBTCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIF90aGlzLmNic1tyZXF1ZXN0LmlkXSA9IHtcbiAgICAgICAgdGltZTogbmV3IERhdGUoKSxcbiAgICAgICAgcmVzb2x2ZTogcmVzb2x2ZSxcbiAgICAgICAgcmVqZWN0OiByZWplY3RcbiAgICAgIH07XG5cbiAgICAgIC8vIFNldCBhbGwgcmVxdWVzdHMgdG8gYmUgJ2NhbGwnIG1ldGhvZHMuXG4gICAgICByZXF1ZXN0Lm1ldGhvZCA9ICdjYWxsJztcblxuICAgICAgdHJ5IHtcbiAgICAgICAgX3RoaXMud3Muc2VuZChKU09OLnN0cmluZ2lmeShyZXF1ZXN0KSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBfdGhpcy5kZWJ1ZygnQ2F1Z2h0IGEgbmFzdHkgZXJyb3IgOiAnLCBlcnJvcik7XG4gICAgICB9XG4gICAgfSk7XG4gIH07XG5cbiAgLyoqXG4gICAqIENhbGxlZCB3aGVuIG1lc3NhZ2VzIGFyZSByZWNlaXZlZCBvbiB0aGUgV2Vic29ja2V0LlxuICAgKlxuICAgKiBAcGFyYW0geyp9IHJlc3BvbnNlIFRoZSBtZXNzYWdlIHJlY2VpdmVkLlxuICAgKiBAbWVtYmVyb2YgQ2hhaW5XZWJTb2NrZXRcbiAgICovXG5cblxuICBDaGFpbldlYlNvY2tldC5wcm90b3R5cGUubGlzdGVuZXIgPSBmdW5jdGlvbiBsaXN0ZW5lcihyZXNwb25zZSkge1xuICAgIHZhciByZXNwb25zZUpTT04gPSBudWxsO1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlc3BvbnNlSlNPTiA9IEpTT04ucGFyc2UocmVzcG9uc2UuZGF0YSk7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHJlc3BvbnNlSlNPTi5lcnJvciA9ICdFcnJvciBwYXJzaW5nIHJlc3BvbnNlOiAnICsgZXJyb3Iuc3RhY2s7XG4gICAgICB0aGlzLmRlYnVnKCdFcnJvciBwYXJzaW5nIHJlc3BvbnNlOiAnLCByZXNwb25zZSk7XG4gICAgfVxuXG4gICAgLy8gQ2xlYXIgdGhlIGhlYWx0aCBjaGVjayB0aW1lb3V0LCB3ZSd2ZSBqdXN0IHJlY2VpdmVkIGEgaGVhbHRoeSByZXNwb25zZSBmcm9tIHRoZSBzZXJ2ZXIuXG4gICAgaWYgKHRoaXMuaGVhbHRoQ2hlY2spIHtcbiAgICAgIGNsZWFyVGltZW91dCh0aGlzLmhlYWx0aENoZWNrKTtcbiAgICAgIHRoaXMuaGVhbHRoQ2hlY2sgPSBudWxsO1xuICAgIH1cblxuICAgIHZhciBzdWIgPSBmYWxzZTtcbiAgICB2YXIgY2FsbGJhY2sgPSBudWxsO1xuXG4gICAgaWYgKHJlc3BvbnNlSlNPTi5tZXRob2QgPT09ICdub3RpY2UnKSB7XG4gICAgICBzdWIgPSB0cnVlO1xuICAgICAgcmVzcG9uc2VKU09OLmlkID0gcmVzcG9uc2VKU09OLnBhcmFtc1swXTtcbiAgICB9XG5cbiAgICBpZiAoIXN1Yikge1xuICAgICAgY2FsbGJhY2sgPSB0aGlzLmNic1tyZXNwb25zZUpTT04uaWRdO1xuICAgIH0gZWxzZSB7XG4gICAgICBjYWxsYmFjayA9IHRoaXMuc3Vic1tyZXNwb25zZUpTT04uaWRdLmNhbGxiYWNrO1xuICAgIH1cblxuICAgIGlmIChjYWxsYmFjayAmJiAhc3ViKSB7XG4gICAgICBpZiAocmVzcG9uc2VKU09OLmVycm9yKSB7XG4gICAgICAgIHRoaXMuZGVidWcoJy0tLS0+IHJlc3BvbnNlSlNPTiA6ICcsIHJlc3BvbnNlSlNPTik7XG4gICAgICAgIGNhbGxiYWNrLnJlamVjdChyZXNwb25zZUpTT04uZXJyb3IpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FsbGJhY2sucmVzb2x2ZShyZXNwb25zZUpTT04ucmVzdWx0KTtcbiAgICAgIH1cblxuICAgICAgZGVsZXRlIHRoaXMuY2JzW3Jlc3BvbnNlSlNPTi5pZF07XG5cbiAgICAgIGlmICh0aGlzLnVuc3ViW3Jlc3BvbnNlSlNPTi5pZF0pIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuc3Vic1t0aGlzLnVuc3ViW3Jlc3BvbnNlSlNPTi5pZF1dO1xuICAgICAgICBkZWxldGUgdGhpcy51bnN1YltyZXNwb25zZUpTT04uaWRdO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY2FsbGJhY2sgJiYgc3ViKSB7XG4gICAgICBjYWxsYmFjayhyZXNwb25zZUpTT04ucGFyYW1zWzFdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kZWJ1ZygnV2FybmluZzogdW5rbm93biB3ZWJzb2NrZXQgcmVzcG9uc2VKU09OOiAnLCByZXNwb25zZUpTT04pO1xuICAgIH1cbiAgfTtcblxuICAvKipcbiAgICogTG9naW4gdG8gdGhlIEJsb2NrY2hhaW4uXG4gICAqXG4gICAqIEBwYXJhbSB7c3RyaW5nfSB1c2VyIFVzZXJuYW1lXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBwYXNzd29yZCBQYXNzd29yZFxuICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgYWZ0ZXIgbG9naW4uXG4gICAqIEBtZW1iZXJvZiBDaGFpbldlYlNvY2tldFxuICAgKi9cblxuXG4gIENoYWluV2ViU29ja2V0LnByb3RvdHlwZS5sb2dpbiA9IGZ1bmN0aW9uIGxvZ2luKHVzZXIsIHBhc3N3b3JkKSB7XG4gICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICB0aGlzLmRlYnVnKCchISEgQ2hhaW5XZWJTb2NrZXQgbG9naW4uJywgdXNlciwgcGFzc3dvcmQpO1xuICAgIHJldHVybiB0aGlzLmNvbm5lY3RfcHJvbWlzZS50aGVuKGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBfdGhpczIuY2FsbChbMSwgJ2xvZ2luJywgW3VzZXIsIHBhc3N3b3JkXV0pO1xuICAgIH0pO1xuICB9O1xuXG4gIC8qKlxuICAgKiBDbG9zZSB0aGUgY29ubmVjdGlvbiB0byB0aGUgQmxvY2tjaGFpbi5cbiAgICpcbiAgICogQG1lbWJlcm9mIENoYWluV2ViU29ja2V0XG4gICAqL1xuXG5cbiAgQ2hhaW5XZWJTb2NrZXQucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gY2xvc2UoKSB7XG4gICAgaWYgKHRoaXMud3MpIHtcbiAgICAgIHRoaXMucmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKTtcblxuICAgICAgLy8gVHJ5IGFuZCBmaXJlIGNsb3NlIG9uIHRoZSBjb25uZWN0aW9uLlxuICAgICAgdGhpcy53cy5jbG9zZSgpO1xuXG4gICAgICAvLyBDbGVhciBvdXIgcmVmZXJlbmNlcyBzbyB0aGF0IGl0IGNhbiBiZSBnYXJiYWdlIGNvbGxlY3RlZC5cbiAgICAgIHRoaXMud3MgPSBudWxsO1xuICAgIH1cblxuICAgIC8vIENsZWFyIG91ciB0aW1lb3V0cyBmb3IgY29ubmVjdGlvbiB0aW1lb3V0IGFuZCBoZWFsdGggY2hlY2suXG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuY29ubmVjdGlvblRpbWVvdXQpO1xuICAgIHRoaXMuY29ubmVjdGlvblRpbWVvdXQgPSBudWxsO1xuXG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuaGVhbHRoQ2hlY2spO1xuICAgIHRoaXMuaGVhbHRoQ2hlY2sgPSBudWxsO1xuXG4gICAgY2xlYXJUaW1lb3V0KHRoaXMucmVjb25uZWN0VGltZW91dCk7XG4gICAgdGhpcy5yZWNvbm5lY3RUaW1lb3V0ID0gbnVsbDtcblxuICAgIC8vIFRvZ2dsZSB0aGUgY29ubmVjdGVkIGZsYWcuXG4gICAgdGhpcy5jb25uZWN0ZWQgPSBmYWxzZTtcbiAgfTtcblxuICBDaGFpbldlYlNvY2tldC5wcm90b3R5cGUuZGVidWcgPSBmdW5jdGlvbiBkZWJ1ZygpIHtcbiAgICBpZiAoU09DS0VUX0RFQlVHKSB7XG4gICAgICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgcGFyYW1zID0gQXJyYXkoX2xlbiksIF9rZXkgPSAwOyBfa2V5IDwgX2xlbjsgX2tleSsrKSB7XG4gICAgICAgIHBhcmFtc1tfa2V5XSA9IGFyZ3VtZW50c1tfa2V5XTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5sb2cuYXBwbHkobnVsbCwgcGFyYW1zKTtcbiAgICB9XG4gIH07XG5cbiAgcmV0dXJuIENoYWluV2ViU29ja2V0O1xufSgpO1xuXG4vLyBDb25zdGFudHMgZm9yIFNUQVRFXG5cblxuQ2hhaW5XZWJTb2NrZXQuc3RhdHVzID0ge1xuICBSRUNPTk5FQ1RFRDogJ3JlY29ubmVjdGVkJyxcbiAgT1BFTjogJ29wZW4nLFxuICBDTE9TRUQ6ICdjbG9zZWQnLFxuICBFUlJPUjogJ2Vycm9yJ1xufTtcblxuZXhwb3J0cy5kZWZhdWx0ID0gQ2hhaW5XZWJTb2NrZXQ7IiwiJ3VzZSBzdHJpY3QnO1xuXG5leHBvcnRzLl9fZXNNb2R1bGUgPSB0cnVlO1xuXG52YXIgX0FwaUluc3RhbmNlcyA9IHJlcXVpcmUoJy4vQXBpSW5zdGFuY2VzJyk7XG5cbnZhciBfQXBpSW5zdGFuY2VzMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX0FwaUluc3RhbmNlcyk7XG5cbnZhciBfQ2hhaW5XZWJTb2NrZXQgPSByZXF1aXJlKCcuL0NoYWluV2ViU29ja2V0Jyk7XG5cbnZhciBfQ2hhaW5XZWJTb2NrZXQyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfQ2hhaW5XZWJTb2NrZXQpO1xuXG5mdW5jdGlvbiBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KG9iaikgeyByZXR1cm4gb2JqICYmIG9iai5fX2VzTW9kdWxlID8gb2JqIDogeyBkZWZhdWx0OiBvYmogfTsgfVxuXG5mdW5jdGlvbiBfY2xhc3NDYWxsQ2hlY2soaW5zdGFuY2UsIENvbnN0cnVjdG9yKSB7IGlmICghKGluc3RhbmNlIGluc3RhbmNlb2YgQ29uc3RydWN0b3IpKSB7IHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb25cIik7IH0gfVxuXG52YXIgTWFuYWdlciA9IGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gTWFuYWdlcihfcmVmKSB7XG4gICAgdmFyIHVybCA9IF9yZWYudXJsLFxuICAgICAgICB1cmxzID0gX3JlZi51cmxzO1xuXG4gICAgX2NsYXNzQ2FsbENoZWNrKHRoaXMsIE1hbmFnZXIpO1xuXG4gICAgdGhpcy51cmwgPSB1cmw7XG4gICAgdGhpcy51cmxzID0gdXJscy5maWx0ZXIoZnVuY3Rpb24gKGEpIHtcbiAgICAgIHJldHVybiBhICE9PSB1cmw7XG4gICAgfSk7XG4gIH1cblxuICBNYW5hZ2VyLnByb3RvdHlwZS5sb2dGYWlsdXJlID0gZnVuY3Rpb24gbG9nRmFpbHVyZSh1cmwpIHtcbiAgICBjb25zb2xlLmVycm9yKCdVbmFibGUgdG8gY29ubmVjdCB0bycsIHVybCArICcsIHNraXBwaW5nIHRvIG5leHQgZnVsbCBub2RlIEFQSSBzZXJ2ZXInKTtcbiAgfTtcblxuICBNYW5hZ2VyLnByb3RvdHlwZS5jb25uZWN0ID0gZnVuY3Rpb24gY29ubmVjdCgpIHtcbiAgICB2YXIgX2Nvbm5lY3QgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6IHRydWU7XG5cbiAgICB2YXIgdXJsID0gYXJndW1lbnRzLmxlbmd0aCA+IDEgJiYgYXJndW1lbnRzWzFdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMV0gOiB0aGlzLnVybDtcblxuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICBfQXBpSW5zdGFuY2VzMi5kZWZhdWx0Lmluc3RhbmNlKHVybCwgX2Nvbm5lY3QpLmluaXRfcHJvbWlzZS50aGVuKHJlc29sdmUpLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICBfQXBpSW5zdGFuY2VzMi5kZWZhdWx0Lmluc3RhbmNlKCkuY2xvc2UoKTtcbiAgICAgICAgcmVqZWN0KGVycm9yKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9O1xuXG4gIE1hbmFnZXIucHJvdG90eXBlLmNvbm5lY3RXaXRoRmFsbGJhY2sgPSBmdW5jdGlvbiBjb25uZWN0V2l0aEZhbGxiYWNrKCkge1xuICAgIHZhciBjb25uZWN0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDAgJiYgYXJndW1lbnRzWzBdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbMF0gOiB0cnVlO1xuICAgIHZhciB1cmwgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHRoaXMudXJsO1xuICAgIHZhciBpbmRleCA9IGFyZ3VtZW50cy5sZW5ndGggPiAyICYmIGFyZ3VtZW50c1syXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzJdIDogMDtcblxuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB2YXIgcmVzb2x2ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAzICYmIGFyZ3VtZW50c1szXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzNdIDogbnVsbDtcbiAgICB2YXIgcmVqZWN0ID0gYXJndW1lbnRzLmxlbmd0aCA+IDQgJiYgYXJndW1lbnRzWzRdICE9PSB1bmRlZmluZWQgPyBhcmd1bWVudHNbNF0gOiBudWxsO1xuXG4gICAgaWYgKHJlamVjdCAmJiBpbmRleCA+IHRoaXMudXJscy5sZW5ndGggLSAxKSB7XG4gICAgICByZXR1cm4gcmVqZWN0KG5ldyBFcnJvcignVHJpZWQgJyArIChpbmRleCArIDEpICsgJyBjb25uZWN0aW9ucywgbm9uZSBvZiB3aGljaCB3b3JrZWQ6ICcgKyBKU09OLnN0cmluZ2lmeSh0aGlzLnVybHMuY29uY2F0KHRoaXMudXJsKSkpKTtcbiAgICB9XG5cbiAgICB2YXIgZmFsbGJhY2sgPSBmdW5jdGlvbiBmYWxsYmFjayhyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIF90aGlzLmxvZ0ZhaWx1cmUodXJsKTtcbiAgICAgIHJldHVybiBfdGhpcy5jb25uZWN0V2l0aEZhbGxiYWNrKGNvbm5lY3QsIF90aGlzLnVybHNbaW5kZXhdLCBpbmRleCArIDEsIHJlc29sdmUsIHJlamVjdCk7XG4gICAgfTtcblxuICAgIGlmIChyZXNvbHZlICYmIHJlamVjdCkge1xuICAgICAgcmV0dXJuIHRoaXMuY29ubmVjdChjb25uZWN0LCB1cmwpLnRoZW4ocmVzb2x2ZSkuY2F0Y2goZnVuY3Rpb24gKCkge1xuICAgICAgICBmYWxsYmFjayhyZXNvbHZlLCByZWplY3QpO1xuICAgICAgfSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIF90aGlzLmNvbm5lY3QoY29ubmVjdCkudGhlbihyZXNvbHZlKS5jYXRjaChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZhbGxiYWNrKHJlc29sdmUsIHJlamVjdCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfTtcblxuICBNYW5hZ2VyLnByb3RvdHlwZS5jaGVja0Nvbm5lY3Rpb25zID0gZnVuY3Rpb24gY2hlY2tDb25uZWN0aW9ucygpIHtcbiAgICB2YXIgcnBjX3VzZXIgPSBhcmd1bWVudHMubGVuZ3RoID4gMCAmJiBhcmd1bWVudHNbMF0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1swXSA6ICcnO1xuICAgIHZhciBycGNfcGFzc3dvcmQgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6ICcnO1xuXG4gICAgdmFyIF90aGlzMiA9IHRoaXM7XG5cbiAgICB2YXIgcmVzb2x2ZSA9IGFyZ3VtZW50c1syXTtcbiAgICB2YXIgcmVqZWN0ID0gYXJndW1lbnRzWzNdO1xuXG4gICAgdmFyIGNvbm5lY3Rpb25TdGFydFRpbWVzID0ge307XG5cbiAgICB2YXIgY2hlY2tGdW5jdGlvbiA9IGZ1bmN0aW9uIGNoZWNrRnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICB2YXIgZnVsbExpc3QgPSBfdGhpczIudXJscy5jb25jYXQoX3RoaXMyLnVybCk7XG4gICAgICB2YXIgY29ubmVjdGlvblByb21pc2VzID0gW107XG5cbiAgICAgIGZ1bGxMaXN0LmZvckVhY2goZnVuY3Rpb24gKHVybCkge1xuICAgICAgICB2YXIgY29ubiA9IG5ldyBfQ2hhaW5XZWJTb2NrZXQyLmRlZmF1bHQodXJsLCBmdW5jdGlvbiAoKSB7fSk7XG4gICAgICAgIGNvbm5lY3Rpb25TdGFydFRpbWVzW3VybF0gPSBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcbiAgICAgICAgY29ubmVjdGlvblByb21pc2VzLnB1c2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgIHJldHVybiBjb25uLmxvZ2luKHJwY191c2VyLCBycGNfcGFzc3dvcmQpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIF9yZWYyO1xuXG4gICAgICAgICAgICBjb25uLmNsb3NlKCk7XG4gICAgICAgICAgICByZXR1cm4gX3JlZjIgPSB7fSwgX3JlZjJbdXJsXSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpIC0gY29ubmVjdGlvblN0YXJ0VGltZXNbdXJsXSwgX3JlZjI7XG4gICAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHVybCA9PT0gX3RoaXMyLnVybCkge1xuICAgICAgICAgICAgICBfdGhpczIudXJsID0gX3RoaXMyLnVybHNbMF07XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICBfdGhpczIudXJscyA9IF90aGlzMi51cmxzLmZpbHRlcihmdW5jdGlvbiAoYSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBhICE9PSB1cmw7XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25uLmNsb3NlKCk7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcblxuICAgICAgUHJvbWlzZS5hbGwoY29ubmVjdGlvblByb21pc2VzLm1hcChmdW5jdGlvbiAoYSkge1xuICAgICAgICByZXR1cm4gYSgpO1xuICAgICAgfSkpLnRoZW4oZnVuY3Rpb24gKHJlcykge1xuICAgICAgICByZXNvbHZlKHJlcy5maWx0ZXIoZnVuY3Rpb24gKGEpIHtcbiAgICAgICAgICByZXR1cm4gISFhO1xuICAgICAgICB9KS5yZWR1Y2UoZnVuY3Rpb24gKGYsIGEpIHtcbiAgICAgICAgICB2YXIga2V5ID0gT2JqZWN0LmtleXMoYSlbMF07XG4gICAgICAgICAgZltrZXldID0gYVtrZXldO1xuICAgICAgICAgIHJldHVybiBmO1xuICAgICAgICB9LCB7fSkpO1xuICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX3RoaXMyLmNoZWNrQ29ubmVjdGlvbnMocnBjX3VzZXIsIHJwY19wYXNzd29yZCwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBpZiAocmVzb2x2ZSAmJiByZWplY3QpIHtcbiAgICAgIGNoZWNrRnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGNoZWNrRnVuY3Rpb24pO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gTWFuYWdlcjtcbn0oKTtcblxuZXhwb3J0cy5kZWZhdWx0ID0gTWFuYWdlcjsiLCIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBHcmFwaGVuZUFwaSA9IGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gR3JhcGhlbmVBcGkod3NfcnBjLCBhcGlfbmFtZSkge1xuICAgIF9jbGFzc0NhbGxDaGVjayh0aGlzLCBHcmFwaGVuZUFwaSk7XG5cbiAgICB0aGlzLndzX3JwYyA9IHdzX3JwYztcbiAgICB0aGlzLmFwaV9uYW1lID0gYXBpX25hbWU7XG4gIH1cblxuICBHcmFwaGVuZUFwaS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uIGluaXQoKSB7XG4gICAgdmFyIF90aGlzID0gdGhpcztcblxuICAgIHJldHVybiB0aGlzLndzX3JwYy5jYWxsKFsxLCB0aGlzLmFwaV9uYW1lLCBbXV0pLnRoZW4oZnVuY3Rpb24gKHJlc3BvbnNlKSB7XG4gICAgICBfdGhpcy5hcGlfaWQgPSByZXNwb25zZTtcbiAgICAgIHJldHVybiBfdGhpcztcbiAgICB9KTtcbiAgfTtcblxuICBHcmFwaGVuZUFwaS5wcm90b3R5cGUuZXhlYyA9IGZ1bmN0aW9uIGV4ZWMobWV0aG9kLCBwYXJhbXMpIHtcbiAgICByZXR1cm4gdGhpcy53c19ycGMuY2FsbChbdGhpcy5hcGlfaWQsIG1ldGhvZCwgcGFyYW1zXSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmxvZygnISEhIEdyYXBoZW5lQXBpIGVycm9yOiAnLCBtZXRob2QsIHBhcmFtcywgZXJyb3IsIEpTT04uc3RyaW5naWZ5KGVycm9yKSk7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9KTtcbiAgfTtcblxuICByZXR1cm4gR3JhcGhlbmVBcGk7XG59KCk7XG5cbmV4cG9ydHMuZGVmYXVsdCA9IEdyYXBoZW5lQXBpOyIsIid1c2Ugc3RyaWN0JztcblxuaWYgKCFwcm9jZXNzLnZlcnNpb24gfHxcbiAgICBwcm9jZXNzLnZlcnNpb24uaW5kZXhPZigndjAuJykgPT09IDAgfHxcbiAgICBwcm9jZXNzLnZlcnNpb24uaW5kZXhPZigndjEuJykgPT09IDAgJiYgcHJvY2Vzcy52ZXJzaW9uLmluZGV4T2YoJ3YxLjguJykgIT09IDApIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSB7IG5leHRUaWNrOiBuZXh0VGljayB9O1xufSBlbHNlIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSBwcm9jZXNzXG59XG5cbmZ1bmN0aW9uIG5leHRUaWNrKGZuLCBhcmcxLCBhcmcyLCBhcmczKSB7XG4gIGlmICh0eXBlb2YgZm4gIT09ICdmdW5jdGlvbicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdcImNhbGxiYWNrXCIgYXJndW1lbnQgbXVzdCBiZSBhIGZ1bmN0aW9uJyk7XG4gIH1cbiAgdmFyIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gIHZhciBhcmdzLCBpO1xuICBzd2l0Y2ggKGxlbikge1xuICBjYXNlIDA6XG4gIGNhc2UgMTpcbiAgICByZXR1cm4gcHJvY2Vzcy5uZXh0VGljayhmbik7XG4gIGNhc2UgMjpcbiAgICByZXR1cm4gcHJvY2Vzcy5uZXh0VGljayhmdW5jdGlvbiBhZnRlclRpY2tPbmUoKSB7XG4gICAgICBmbi5jYWxsKG51bGwsIGFyZzEpO1xuICAgIH0pO1xuICBjYXNlIDM6XG4gICAgcmV0dXJuIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24gYWZ0ZXJUaWNrVHdvKCkge1xuICAgICAgZm4uY2FsbChudWxsLCBhcmcxLCBhcmcyKTtcbiAgICB9KTtcbiAgY2FzZSA0OlxuICAgIHJldHVybiBwcm9jZXNzLm5leHRUaWNrKGZ1bmN0aW9uIGFmdGVyVGlja1RocmVlKCkge1xuICAgICAgZm4uY2FsbChudWxsLCBhcmcxLCBhcmcyLCBhcmczKTtcbiAgICB9KTtcbiAgZGVmYXVsdDpcbiAgICBhcmdzID0gbmV3IEFycmF5KGxlbiAtIDEpO1xuICAgIGkgPSAwO1xuICAgIHdoaWxlIChpIDwgYXJncy5sZW5ndGgpIHtcbiAgICAgIGFyZ3NbaSsrXSA9IGFyZ3VtZW50c1tpXTtcbiAgICB9XG4gICAgcmV0dXJuIHByb2Nlc3MubmV4dFRpY2soZnVuY3Rpb24gYWZ0ZXJUaWNrKCkge1xuICAgICAgZm4uYXBwbHkobnVsbCwgYXJncyk7XG4gICAgfSk7XG4gIH1cbn1cblxuIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG52YXIgcHJvY2VzcyA9IG1vZHVsZS5leHBvcnRzID0ge307XG5cbi8vIGNhY2hlZCBmcm9tIHdoYXRldmVyIGdsb2JhbCBpcyBwcmVzZW50IHNvIHRoYXQgdGVzdCBydW5uZXJzIHRoYXQgc3R1YiBpdFxuLy8gZG9uJ3QgYnJlYWsgdGhpbmdzLiAgQnV0IHdlIG5lZWQgdG8gd3JhcCBpdCBpbiBhIHRyeSBjYXRjaCBpbiBjYXNlIGl0IGlzXG4vLyB3cmFwcGVkIGluIHN0cmljdCBtb2RlIGNvZGUgd2hpY2ggZG9lc24ndCBkZWZpbmUgYW55IGdsb2JhbHMuICBJdCdzIGluc2lkZSBhXG4vLyBmdW5jdGlvbiBiZWNhdXNlIHRyeS9jYXRjaGVzIGRlb3B0aW1pemUgaW4gY2VydGFpbiBlbmdpbmVzLlxuXG52YXIgY2FjaGVkU2V0VGltZW91dDtcbnZhciBjYWNoZWRDbGVhclRpbWVvdXQ7XG5cbmZ1bmN0aW9uIGRlZmF1bHRTZXRUaW1vdXQoKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdzZXRUaW1lb3V0IGhhcyBub3QgYmVlbiBkZWZpbmVkJyk7XG59XG5mdW5jdGlvbiBkZWZhdWx0Q2xlYXJUaW1lb3V0ICgpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ2NsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCcpO1xufVxuKGZ1bmN0aW9uICgpIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIHNldFRpbWVvdXQgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBzZXRUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IGRlZmF1bHRTZXRUaW1vdXQ7XG4gICAgICAgIH1cbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGNhY2hlZFNldFRpbWVvdXQgPSBkZWZhdWx0U2V0VGltb3V0O1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgICBpZiAodHlwZW9mIGNsZWFyVGltZW91dCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gY2xlYXJUaW1lb3V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY2FjaGVkQ2xlYXJUaW1lb3V0ID0gZGVmYXVsdENsZWFyVGltZW91dDtcbiAgICB9XG59ICgpKVxuZnVuY3Rpb24gcnVuVGltZW91dChmdW4pIHtcbiAgICBpZiAoY2FjaGVkU2V0VGltZW91dCA9PT0gc2V0VGltZW91dCkge1xuICAgICAgICAvL25vcm1hbCBlbnZpcm9tZW50cyBpbiBzYW5lIHNpdHVhdGlvbnNcbiAgICAgICAgcmV0dXJuIHNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9XG4gICAgLy8gaWYgc2V0VGltZW91dCB3YXNuJ3QgYXZhaWxhYmxlIGJ1dCB3YXMgbGF0dGVyIGRlZmluZWRcbiAgICBpZiAoKGNhY2hlZFNldFRpbWVvdXQgPT09IGRlZmF1bHRTZXRUaW1vdXQgfHwgIWNhY2hlZFNldFRpbWVvdXQpICYmIHNldFRpbWVvdXQpIHtcbiAgICAgICAgY2FjaGVkU2V0VGltZW91dCA9IHNldFRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBzZXRUaW1lb3V0KGZ1biwgMCk7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICAgIC8vIHdoZW4gd2hlbiBzb21lYm9keSBoYXMgc2NyZXdlZCB3aXRoIHNldFRpbWVvdXQgYnV0IG5vIEkuRS4gbWFkZG5lc3NcbiAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQoZnVuLCAwKTtcbiAgICB9IGNhdGNoKGUpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgLy8gV2hlbiB3ZSBhcmUgaW4gSS5FLiBidXQgdGhlIHNjcmlwdCBoYXMgYmVlbiBldmFsZWQgc28gSS5FLiBkb2Vzbid0IHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkU2V0VGltZW91dC5jYWxsKG51bGwsIGZ1biwgMCk7XG4gICAgICAgIH0gY2F0Y2goZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvclxuICAgICAgICAgICAgcmV0dXJuIGNhY2hlZFNldFRpbWVvdXQuY2FsbCh0aGlzLCBmdW4sIDApO1xuICAgICAgICB9XG4gICAgfVxuXG5cbn1cbmZ1bmN0aW9uIHJ1bkNsZWFyVGltZW91dChtYXJrZXIpIHtcbiAgICBpZiAoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBjbGVhclRpbWVvdXQpIHtcbiAgICAgICAgLy9ub3JtYWwgZW52aXJvbWVudHMgaW4gc2FuZSBzaXR1YXRpb25zXG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgLy8gaWYgY2xlYXJUaW1lb3V0IHdhc24ndCBhdmFpbGFibGUgYnV0IHdhcyBsYXR0ZXIgZGVmaW5lZFxuICAgIGlmICgoY2FjaGVkQ2xlYXJUaW1lb3V0ID09PSBkZWZhdWx0Q2xlYXJUaW1lb3V0IHx8ICFjYWNoZWRDbGVhclRpbWVvdXQpICYmIGNsZWFyVGltZW91dCkge1xuICAgICAgICBjYWNoZWRDbGVhclRpbWVvdXQgPSBjbGVhclRpbWVvdXQ7XG4gICAgICAgIHJldHVybiBjbGVhclRpbWVvdXQobWFya2VyKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgICAgLy8gd2hlbiB3aGVuIHNvbWVib2R5IGhhcyBzY3Jld2VkIHdpdGggc2V0VGltZW91dCBidXQgbm8gSS5FLiBtYWRkbmVzc1xuICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0KG1hcmtlcik7XG4gICAgfSBjYXRjaCAoZSl7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICAvLyBXaGVuIHdlIGFyZSBpbiBJLkUuIGJ1dCB0aGUgc2NyaXB0IGhhcyBiZWVuIGV2YWxlZCBzbyBJLkUuIGRvZXNuJ3QgIHRydXN0IHRoZSBnbG9iYWwgb2JqZWN0IHdoZW4gY2FsbGVkIG5vcm1hbGx5XG4gICAgICAgICAgICByZXR1cm4gY2FjaGVkQ2xlYXJUaW1lb3V0LmNhbGwobnVsbCwgbWFya2VyKTtcbiAgICAgICAgfSBjYXRjaCAoZSl7XG4gICAgICAgICAgICAvLyBzYW1lIGFzIGFib3ZlIGJ1dCB3aGVuIGl0J3MgYSB2ZXJzaW9uIG9mIEkuRS4gdGhhdCBtdXN0IGhhdmUgdGhlIGdsb2JhbCBvYmplY3QgZm9yICd0aGlzJywgaG9wZnVsbHkgb3VyIGNvbnRleHQgY29ycmVjdCBvdGhlcndpc2UgaXQgd2lsbCB0aHJvdyBhIGdsb2JhbCBlcnJvci5cbiAgICAgICAgICAgIC8vIFNvbWUgdmVyc2lvbnMgb2YgSS5FLiBoYXZlIGRpZmZlcmVudCBydWxlcyBmb3IgY2xlYXJUaW1lb3V0IHZzIHNldFRpbWVvdXRcbiAgICAgICAgICAgIHJldHVybiBjYWNoZWRDbGVhclRpbWVvdXQuY2FsbCh0aGlzLCBtYXJrZXIpO1xuICAgICAgICB9XG4gICAgfVxuXG5cblxufVxudmFyIHF1ZXVlID0gW107XG52YXIgZHJhaW5pbmcgPSBmYWxzZTtcbnZhciBjdXJyZW50UXVldWU7XG52YXIgcXVldWVJbmRleCA9IC0xO1xuXG5mdW5jdGlvbiBjbGVhblVwTmV4dFRpY2soKSB7XG4gICAgaWYgKCFkcmFpbmluZyB8fCAhY3VycmVudFF1ZXVlKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG4gICAgZHJhaW5pbmcgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudFF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBxdWV1ZSA9IGN1cnJlbnRRdWV1ZS5jb25jYXQocXVldWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICB9XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCkge1xuICAgICAgICBkcmFpblF1ZXVlKCk7XG4gICAgfVxufVxuXG5mdW5jdGlvbiBkcmFpblF1ZXVlKCkge1xuICAgIGlmIChkcmFpbmluZykge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIHZhciB0aW1lb3V0ID0gcnVuVGltZW91dChjbGVhblVwTmV4dFRpY2spO1xuICAgIGRyYWluaW5nID0gdHJ1ZTtcblxuICAgIHZhciBsZW4gPSBxdWV1ZS5sZW5ndGg7XG4gICAgd2hpbGUobGVuKSB7XG4gICAgICAgIGN1cnJlbnRRdWV1ZSA9IHF1ZXVlO1xuICAgICAgICBxdWV1ZSA9IFtdO1xuICAgICAgICB3aGlsZSAoKytxdWV1ZUluZGV4IDwgbGVuKSB7XG4gICAgICAgICAgICBpZiAoY3VycmVudFF1ZXVlKSB7XG4gICAgICAgICAgICAgICAgY3VycmVudFF1ZXVlW3F1ZXVlSW5kZXhdLnJ1bigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHF1ZXVlSW5kZXggPSAtMTtcbiAgICAgICAgbGVuID0gcXVldWUubGVuZ3RoO1xuICAgIH1cbiAgICBjdXJyZW50UXVldWUgPSBudWxsO1xuICAgIGRyYWluaW5nID0gZmFsc2U7XG4gICAgcnVuQ2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xufVxuXG5wcm9jZXNzLm5leHRUaWNrID0gZnVuY3Rpb24gKGZ1bikge1xuICAgIHZhciBhcmdzID0gbmV3IEFycmF5KGFyZ3VtZW50cy5sZW5ndGggLSAxKTtcbiAgICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBhcmd1bWVudHMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGFyZ3NbaSAtIDFdID0gYXJndW1lbnRzW2ldO1xuICAgICAgICB9XG4gICAgfVxuICAgIHF1ZXVlLnB1c2gobmV3IEl0ZW0oZnVuLCBhcmdzKSk7XG4gICAgaWYgKHF1ZXVlLmxlbmd0aCA9PT0gMSAmJiAhZHJhaW5pbmcpIHtcbiAgICAgICAgcnVuVGltZW91dChkcmFpblF1ZXVlKTtcbiAgICB9XG59O1xuXG4vLyB2OCBsaWtlcyBwcmVkaWN0aWJsZSBvYmplY3RzXG5mdW5jdGlvbiBJdGVtKGZ1biwgYXJyYXkpIHtcbiAgICB0aGlzLmZ1biA9IGZ1bjtcbiAgICB0aGlzLmFycmF5ID0gYXJyYXk7XG59XG5JdGVtLnByb3RvdHlwZS5ydW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgdGhpcy5mdW4uYXBwbHkobnVsbCwgdGhpcy5hcnJheSk7XG59O1xucHJvY2Vzcy50aXRsZSA9ICdicm93c2VyJztcbnByb2Nlc3MuYnJvd3NlciA9IHRydWU7XG5wcm9jZXNzLmVudiA9IHt9O1xucHJvY2Vzcy5hcmd2ID0gW107XG5wcm9jZXNzLnZlcnNpb24gPSAnJzsgLy8gZW1wdHkgc3RyaW5nIHRvIGF2b2lkIHJlZ2V4cCBpc3N1ZXNcbnByb2Nlc3MudmVyc2lvbnMgPSB7fTtcblxuZnVuY3Rpb24gbm9vcCgpIHt9XG5cbnByb2Nlc3Mub24gPSBub29wO1xucHJvY2Vzcy5hZGRMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLm9uY2UgPSBub29wO1xucHJvY2Vzcy5vZmYgPSBub29wO1xucHJvY2Vzcy5yZW1vdmVMaXN0ZW5lciA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUFsbExpc3RlbmVycyA9IG5vb3A7XG5wcm9jZXNzLmVtaXQgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kTGlzdGVuZXIgPSBub29wO1xucHJvY2Vzcy5wcmVwZW5kT25jZUxpc3RlbmVyID0gbm9vcDtcblxucHJvY2Vzcy5saXN0ZW5lcnMgPSBmdW5jdGlvbiAobmFtZSkgeyByZXR1cm4gW10gfVxuXG5wcm9jZXNzLmJpbmRpbmcgPSBmdW5jdGlvbiAobmFtZSkge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG5cbnByb2Nlc3MuY3dkID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gJy8nIH07XG5wcm9jZXNzLmNoZGlyID0gZnVuY3Rpb24gKGRpcikge1xuICAgIHRocm93IG5ldyBFcnJvcigncHJvY2Vzcy5jaGRpciBpcyBub3Qgc3VwcG9ydGVkJyk7XG59O1xucHJvY2Vzcy51bWFzayA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gMDsgfTtcbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9saWIvX3N0cmVhbV9kdXBsZXguanMnKTtcbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4vLyBhIGR1cGxleCBzdHJlYW0gaXMganVzdCBhIHN0cmVhbSB0aGF0IGlzIGJvdGggcmVhZGFibGUgYW5kIHdyaXRhYmxlLlxuLy8gU2luY2UgSlMgZG9lc24ndCBoYXZlIG11bHRpcGxlIHByb3RvdHlwYWwgaW5oZXJpdGFuY2UsIHRoaXMgY2xhc3Ncbi8vIHByb3RvdHlwYWxseSBpbmhlcml0cyBmcm9tIFJlYWRhYmxlLCBhbmQgdGhlbiBwYXJhc2l0aWNhbGx5IGZyb21cbi8vIFdyaXRhYmxlLlxuXG4ndXNlIHN0cmljdCc7XG5cbi8qPHJlcGxhY2VtZW50PiovXG5cbnZhciBwbmEgPSByZXF1aXJlKCdwcm9jZXNzLW5leHRpY2stYXJncycpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgb2JqZWN0S2V5cyA9IE9iamVjdC5rZXlzIHx8IGZ1bmN0aW9uIChvYmopIHtcbiAgdmFyIGtleXMgPSBbXTtcbiAgZm9yICh2YXIga2V5IGluIG9iaikge1xuICAgIGtleXMucHVzaChrZXkpO1xuICB9cmV0dXJuIGtleXM7XG59O1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbm1vZHVsZS5leHBvcnRzID0gRHVwbGV4O1xuXG4vKjxyZXBsYWNlbWVudD4qL1xudmFyIHV0aWwgPSByZXF1aXJlKCdjb3JlLXV0aWwtaXMnKTtcbnV0aWwuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbnZhciBSZWFkYWJsZSA9IHJlcXVpcmUoJy4vX3N0cmVhbV9yZWFkYWJsZScpO1xudmFyIFdyaXRhYmxlID0gcmVxdWlyZSgnLi9fc3RyZWFtX3dyaXRhYmxlJyk7XG5cbnV0aWwuaW5oZXJpdHMoRHVwbGV4LCBSZWFkYWJsZSk7XG5cbntcbiAgLy8gYXZvaWQgc2NvcGUgY3JlZXAsIHRoZSBrZXlzIGFycmF5IGNhbiB0aGVuIGJlIGNvbGxlY3RlZFxuICB2YXIga2V5cyA9IG9iamVjdEtleXMoV3JpdGFibGUucHJvdG90eXBlKTtcbiAgZm9yICh2YXIgdiA9IDA7IHYgPCBrZXlzLmxlbmd0aDsgdisrKSB7XG4gICAgdmFyIG1ldGhvZCA9IGtleXNbdl07XG4gICAgaWYgKCFEdXBsZXgucHJvdG90eXBlW21ldGhvZF0pIER1cGxleC5wcm90b3R5cGVbbWV0aG9kXSA9IFdyaXRhYmxlLnByb3RvdHlwZVttZXRob2RdO1xuICB9XG59XG5cbmZ1bmN0aW9uIER1cGxleChvcHRpb25zKSB7XG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBEdXBsZXgpKSByZXR1cm4gbmV3IER1cGxleChvcHRpb25zKTtcblxuICBSZWFkYWJsZS5jYWxsKHRoaXMsIG9wdGlvbnMpO1xuICBXcml0YWJsZS5jYWxsKHRoaXMsIG9wdGlvbnMpO1xuXG4gIGlmIChvcHRpb25zICYmIG9wdGlvbnMucmVhZGFibGUgPT09IGZhbHNlKSB0aGlzLnJlYWRhYmxlID0gZmFsc2U7XG5cbiAgaWYgKG9wdGlvbnMgJiYgb3B0aW9ucy53cml0YWJsZSA9PT0gZmFsc2UpIHRoaXMud3JpdGFibGUgPSBmYWxzZTtcblxuICB0aGlzLmFsbG93SGFsZk9wZW4gPSB0cnVlO1xuICBpZiAob3B0aW9ucyAmJiBvcHRpb25zLmFsbG93SGFsZk9wZW4gPT09IGZhbHNlKSB0aGlzLmFsbG93SGFsZk9wZW4gPSBmYWxzZTtcblxuICB0aGlzLm9uY2UoJ2VuZCcsIG9uZW5kKTtcbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KER1cGxleC5wcm90b3R5cGUsICd3cml0YWJsZUhpZ2hXYXRlck1hcmsnLCB7XG4gIC8vIG1ha2luZyBpdCBleHBsaWNpdCB0aGlzIHByb3BlcnR5IGlzIG5vdCBlbnVtZXJhYmxlXG4gIC8vIGJlY2F1c2Ugb3RoZXJ3aXNlIHNvbWUgcHJvdG90eXBlIG1hbmlwdWxhdGlvbiBpblxuICAvLyB1c2VybGFuZCB3aWxsIGZhaWxcbiAgZW51bWVyYWJsZTogZmFsc2UsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl93cml0YWJsZVN0YXRlLmhpZ2hXYXRlck1hcms7XG4gIH1cbn0pO1xuXG4vLyB0aGUgbm8taGFsZi1vcGVuIGVuZm9yY2VyXG5mdW5jdGlvbiBvbmVuZCgpIHtcbiAgLy8gaWYgd2UgYWxsb3cgaGFsZi1vcGVuIHN0YXRlLCBvciBpZiB0aGUgd3JpdGFibGUgc2lkZSBlbmRlZCxcbiAgLy8gdGhlbiB3ZSdyZSBvay5cbiAgaWYgKHRoaXMuYWxsb3dIYWxmT3BlbiB8fCB0aGlzLl93cml0YWJsZVN0YXRlLmVuZGVkKSByZXR1cm47XG5cbiAgLy8gbm8gbW9yZSBkYXRhIGNhbiBiZSB3cml0dGVuLlxuICAvLyBCdXQgYWxsb3cgbW9yZSB3cml0ZXMgdG8gaGFwcGVuIGluIHRoaXMgdGljay5cbiAgcG5hLm5leHRUaWNrKG9uRW5kTlQsIHRoaXMpO1xufVxuXG5mdW5jdGlvbiBvbkVuZE5UKHNlbGYpIHtcbiAgc2VsZi5lbmQoKTtcbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KER1cGxleC5wcm90b3R5cGUsICdkZXN0cm95ZWQnLCB7XG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLl9yZWFkYWJsZVN0YXRlID09PSB1bmRlZmluZWQgfHwgdGhpcy5fd3JpdGFibGVTdGF0ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiB0aGlzLl9yZWFkYWJsZVN0YXRlLmRlc3Ryb3llZCAmJiB0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZDtcbiAgfSxcbiAgc2V0OiBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAvLyB3ZSBpZ25vcmUgdGhlIHZhbHVlIGlmIHRoZSBzdHJlYW1cbiAgICAvLyBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWQgeWV0XG4gICAgaWYgKHRoaXMuX3JlYWRhYmxlU3RhdGUgPT09IHVuZGVmaW5lZCB8fCB0aGlzLl93cml0YWJsZVN0YXRlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LCB0aGUgdXNlciBpcyBleHBsaWNpdGx5XG4gICAgLy8gbWFuYWdpbmcgZGVzdHJveWVkXG4gICAgdGhpcy5fcmVhZGFibGVTdGF0ZS5kZXN0cm95ZWQgPSB2YWx1ZTtcbiAgICB0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZCA9IHZhbHVlO1xuICB9XG59KTtcblxuRHVwbGV4LnByb3RvdHlwZS5fZGVzdHJveSA9IGZ1bmN0aW9uIChlcnIsIGNiKSB7XG4gIHRoaXMucHVzaChudWxsKTtcbiAgdGhpcy5lbmQoKTtcblxuICBwbmEubmV4dFRpY2soY2IsIGVycik7XG59OyIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4vLyBhIHBhc3N0aHJvdWdoIHN0cmVhbS5cbi8vIGJhc2ljYWxseSBqdXN0IHRoZSBtb3N0IG1pbmltYWwgc29ydCBvZiBUcmFuc2Zvcm0gc3RyZWFtLlxuLy8gRXZlcnkgd3JpdHRlbiBjaHVuayBnZXRzIG91dHB1dCBhcy1pcy5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFBhc3NUaHJvdWdoO1xuXG52YXIgVHJhbnNmb3JtID0gcmVxdWlyZSgnLi9fc3RyZWFtX3RyYW5zZm9ybScpO1xuXG4vKjxyZXBsYWNlbWVudD4qL1xudmFyIHV0aWwgPSByZXF1aXJlKCdjb3JlLXV0aWwtaXMnKTtcbnV0aWwuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbnV0aWwuaW5oZXJpdHMoUGFzc1Rocm91Z2gsIFRyYW5zZm9ybSk7XG5cbmZ1bmN0aW9uIFBhc3NUaHJvdWdoKG9wdGlvbnMpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFBhc3NUaHJvdWdoKSkgcmV0dXJuIG5ldyBQYXNzVGhyb3VnaChvcHRpb25zKTtcblxuICBUcmFuc2Zvcm0uY2FsbCh0aGlzLCBvcHRpb25zKTtcbn1cblxuUGFzc1Rocm91Z2gucHJvdG90eXBlLl90cmFuc2Zvcm0gPSBmdW5jdGlvbiAoY2h1bmssIGVuY29kaW5nLCBjYikge1xuICBjYihudWxsLCBjaHVuayk7XG59OyIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG4ndXNlIHN0cmljdCc7XG5cbi8qPHJlcGxhY2VtZW50PiovXG5cbnZhciBwbmEgPSByZXF1aXJlKCdwcm9jZXNzLW5leHRpY2stYXJncycpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbm1vZHVsZS5leHBvcnRzID0gUmVhZGFibGU7XG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgaXNBcnJheSA9IHJlcXVpcmUoJ2lzYXJyYXknKTtcbi8qPC9yZXBsYWNlbWVudD4qL1xuXG4vKjxyZXBsYWNlbWVudD4qL1xudmFyIER1cGxleDtcbi8qPC9yZXBsYWNlbWVudD4qL1xuXG5SZWFkYWJsZS5SZWFkYWJsZVN0YXRlID0gUmVhZGFibGVTdGF0ZTtcblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBFRSA9IHJlcXVpcmUoJ2V2ZW50cycpLkV2ZW50RW1pdHRlcjtcblxudmFyIEVFbGlzdGVuZXJDb3VudCA9IGZ1bmN0aW9uIChlbWl0dGVyLCB0eXBlKSB7XG4gIHJldHVybiBlbWl0dGVyLmxpc3RlbmVycyh0eXBlKS5sZW5ndGg7XG59O1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgU3RyZWFtID0gcmVxdWlyZSgnLi9pbnRlcm5hbC9zdHJlYW1zL3N0cmVhbScpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbi8qPHJlcGxhY2VtZW50PiovXG5cbnZhciBCdWZmZXIgPSByZXF1aXJlKCdzYWZlLWJ1ZmZlcicpLkJ1ZmZlcjtcbnZhciBPdXJVaW50OEFycmF5ID0gZ2xvYmFsLlVpbnQ4QXJyYXkgfHwgZnVuY3Rpb24gKCkge307XG5mdW5jdGlvbiBfdWludDhBcnJheVRvQnVmZmVyKGNodW5rKSB7XG4gIHJldHVybiBCdWZmZXIuZnJvbShjaHVuayk7XG59XG5mdW5jdGlvbiBfaXNVaW50OEFycmF5KG9iaikge1xuICByZXR1cm4gQnVmZmVyLmlzQnVmZmVyKG9iaikgfHwgb2JqIGluc3RhbmNlb2YgT3VyVWludDhBcnJheTtcbn1cblxuLyo8L3JlcGxhY2VtZW50PiovXG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgdXRpbCA9IHJlcXVpcmUoJ2NvcmUtdXRpbC1pcycpO1xudXRpbC5pbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBkZWJ1Z1V0aWwgPSByZXF1aXJlKCd1dGlsJyk7XG52YXIgZGVidWcgPSB2b2lkIDA7XG5pZiAoZGVidWdVdGlsICYmIGRlYnVnVXRpbC5kZWJ1Z2xvZykge1xuICBkZWJ1ZyA9IGRlYnVnVXRpbC5kZWJ1Z2xvZygnc3RyZWFtJyk7XG59IGVsc2Uge1xuICBkZWJ1ZyA9IGZ1bmN0aW9uICgpIHt9O1xufVxuLyo8L3JlcGxhY2VtZW50PiovXG5cbnZhciBCdWZmZXJMaXN0ID0gcmVxdWlyZSgnLi9pbnRlcm5hbC9zdHJlYW1zL0J1ZmZlckxpc3QnKTtcbnZhciBkZXN0cm95SW1wbCA9IHJlcXVpcmUoJy4vaW50ZXJuYWwvc3RyZWFtcy9kZXN0cm95Jyk7XG52YXIgU3RyaW5nRGVjb2RlcjtcblxudXRpbC5pbmhlcml0cyhSZWFkYWJsZSwgU3RyZWFtKTtcblxudmFyIGtQcm94eUV2ZW50cyA9IFsnZXJyb3InLCAnY2xvc2UnLCAnZGVzdHJveScsICdwYXVzZScsICdyZXN1bWUnXTtcblxuZnVuY3Rpb24gcHJlcGVuZExpc3RlbmVyKGVtaXR0ZXIsIGV2ZW50LCBmbikge1xuICAvLyBTYWRseSB0aGlzIGlzIG5vdCBjYWNoZWFibGUgYXMgc29tZSBsaWJyYXJpZXMgYnVuZGxlIHRoZWlyIG93blxuICAvLyBldmVudCBlbWl0dGVyIGltcGxlbWVudGF0aW9uIHdpdGggdGhlbS5cbiAgaWYgKHR5cGVvZiBlbWl0dGVyLnByZXBlbmRMaXN0ZW5lciA9PT0gJ2Z1bmN0aW9uJykgcmV0dXJuIGVtaXR0ZXIucHJlcGVuZExpc3RlbmVyKGV2ZW50LCBmbik7XG5cbiAgLy8gVGhpcyBpcyBhIGhhY2sgdG8gbWFrZSBzdXJlIHRoYXQgb3VyIGVycm9yIGhhbmRsZXIgaXMgYXR0YWNoZWQgYmVmb3JlIGFueVxuICAvLyB1c2VybGFuZCBvbmVzLiAgTkVWRVIgRE8gVEhJUy4gVGhpcyBpcyBoZXJlIG9ubHkgYmVjYXVzZSB0aGlzIGNvZGUgbmVlZHNcbiAgLy8gdG8gY29udGludWUgdG8gd29yayB3aXRoIG9sZGVyIHZlcnNpb25zIG9mIE5vZGUuanMgdGhhdCBkbyBub3QgaW5jbHVkZVxuICAvLyB0aGUgcHJlcGVuZExpc3RlbmVyKCkgbWV0aG9kLiBUaGUgZ29hbCBpcyB0byBldmVudHVhbGx5IHJlbW92ZSB0aGlzIGhhY2suXG4gIGlmICghZW1pdHRlci5fZXZlbnRzIHx8ICFlbWl0dGVyLl9ldmVudHNbZXZlbnRdKSBlbWl0dGVyLm9uKGV2ZW50LCBmbik7ZWxzZSBpZiAoaXNBcnJheShlbWl0dGVyLl9ldmVudHNbZXZlbnRdKSkgZW1pdHRlci5fZXZlbnRzW2V2ZW50XS51bnNoaWZ0KGZuKTtlbHNlIGVtaXR0ZXIuX2V2ZW50c1tldmVudF0gPSBbZm4sIGVtaXR0ZXIuX2V2ZW50c1tldmVudF1dO1xufVxuXG5mdW5jdGlvbiBSZWFkYWJsZVN0YXRlKG9wdGlvbnMsIHN0cmVhbSkge1xuICBEdXBsZXggPSBEdXBsZXggfHwgcmVxdWlyZSgnLi9fc3RyZWFtX2R1cGxleCcpO1xuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIC8vIER1cGxleCBzdHJlYW1zIGFyZSBib3RoIHJlYWRhYmxlIGFuZCB3cml0YWJsZSwgYnV0IHNoYXJlXG4gIC8vIHRoZSBzYW1lIG9wdGlvbnMgb2JqZWN0LlxuICAvLyBIb3dldmVyLCBzb21lIGNhc2VzIHJlcXVpcmUgc2V0dGluZyBvcHRpb25zIHRvIGRpZmZlcmVudFxuICAvLyB2YWx1ZXMgZm9yIHRoZSByZWFkYWJsZSBhbmQgdGhlIHdyaXRhYmxlIHNpZGVzIG9mIHRoZSBkdXBsZXggc3RyZWFtLlxuICAvLyBUaGVzZSBvcHRpb25zIGNhbiBiZSBwcm92aWRlZCBzZXBhcmF0ZWx5IGFzIHJlYWRhYmxlWFhYIGFuZCB3cml0YWJsZVhYWC5cbiAgdmFyIGlzRHVwbGV4ID0gc3RyZWFtIGluc3RhbmNlb2YgRHVwbGV4O1xuXG4gIC8vIG9iamVjdCBzdHJlYW0gZmxhZy4gVXNlZCB0byBtYWtlIHJlYWQobikgaWdub3JlIG4gYW5kIHRvXG4gIC8vIG1ha2UgYWxsIHRoZSBidWZmZXIgbWVyZ2luZyBhbmQgbGVuZ3RoIGNoZWNrcyBnbyBhd2F5XG4gIHRoaXMub2JqZWN0TW9kZSA9ICEhb3B0aW9ucy5vYmplY3RNb2RlO1xuXG4gIGlmIChpc0R1cGxleCkgdGhpcy5vYmplY3RNb2RlID0gdGhpcy5vYmplY3RNb2RlIHx8ICEhb3B0aW9ucy5yZWFkYWJsZU9iamVjdE1vZGU7XG5cbiAgLy8gdGhlIHBvaW50IGF0IHdoaWNoIGl0IHN0b3BzIGNhbGxpbmcgX3JlYWQoKSB0byBmaWxsIHRoZSBidWZmZXJcbiAgLy8gTm90ZTogMCBpcyBhIHZhbGlkIHZhbHVlLCBtZWFucyBcImRvbid0IGNhbGwgX3JlYWQgcHJlZW1wdGl2ZWx5IGV2ZXJcIlxuICB2YXIgaHdtID0gb3B0aW9ucy5oaWdoV2F0ZXJNYXJrO1xuICB2YXIgcmVhZGFibGVId20gPSBvcHRpb25zLnJlYWRhYmxlSGlnaFdhdGVyTWFyaztcbiAgdmFyIGRlZmF1bHRId20gPSB0aGlzLm9iamVjdE1vZGUgPyAxNiA6IDE2ICogMTAyNDtcblxuICBpZiAoaHdtIHx8IGh3bSA9PT0gMCkgdGhpcy5oaWdoV2F0ZXJNYXJrID0gaHdtO2Vsc2UgaWYgKGlzRHVwbGV4ICYmIChyZWFkYWJsZUh3bSB8fCByZWFkYWJsZUh3bSA9PT0gMCkpIHRoaXMuaGlnaFdhdGVyTWFyayA9IHJlYWRhYmxlSHdtO2Vsc2UgdGhpcy5oaWdoV2F0ZXJNYXJrID0gZGVmYXVsdEh3bTtcblxuICAvLyBjYXN0IHRvIGludHMuXG4gIHRoaXMuaGlnaFdhdGVyTWFyayA9IE1hdGguZmxvb3IodGhpcy5oaWdoV2F0ZXJNYXJrKTtcblxuICAvLyBBIGxpbmtlZCBsaXN0IGlzIHVzZWQgdG8gc3RvcmUgZGF0YSBjaHVua3MgaW5zdGVhZCBvZiBhbiBhcnJheSBiZWNhdXNlIHRoZVxuICAvLyBsaW5rZWQgbGlzdCBjYW4gcmVtb3ZlIGVsZW1lbnRzIGZyb20gdGhlIGJlZ2lubmluZyBmYXN0ZXIgdGhhblxuICAvLyBhcnJheS5zaGlmdCgpXG4gIHRoaXMuYnVmZmVyID0gbmV3IEJ1ZmZlckxpc3QoKTtcbiAgdGhpcy5sZW5ndGggPSAwO1xuICB0aGlzLnBpcGVzID0gbnVsbDtcbiAgdGhpcy5waXBlc0NvdW50ID0gMDtcbiAgdGhpcy5mbG93aW5nID0gbnVsbDtcbiAgdGhpcy5lbmRlZCA9IGZhbHNlO1xuICB0aGlzLmVuZEVtaXR0ZWQgPSBmYWxzZTtcbiAgdGhpcy5yZWFkaW5nID0gZmFsc2U7XG5cbiAgLy8gYSBmbGFnIHRvIGJlIGFibGUgdG8gdGVsbCBpZiB0aGUgZXZlbnQgJ3JlYWRhYmxlJy8nZGF0YScgaXMgZW1pdHRlZFxuICAvLyBpbW1lZGlhdGVseSwgb3Igb24gYSBsYXRlciB0aWNrLiAgV2Ugc2V0IHRoaXMgdG8gdHJ1ZSBhdCBmaXJzdCwgYmVjYXVzZVxuICAvLyBhbnkgYWN0aW9ucyB0aGF0IHNob3VsZG4ndCBoYXBwZW4gdW50aWwgXCJsYXRlclwiIHNob3VsZCBnZW5lcmFsbHkgYWxzb1xuICAvLyBub3QgaGFwcGVuIGJlZm9yZSB0aGUgZmlyc3QgcmVhZCBjYWxsLlxuICB0aGlzLnN5bmMgPSB0cnVlO1xuXG4gIC8vIHdoZW5ldmVyIHdlIHJldHVybiBudWxsLCB0aGVuIHdlIHNldCBhIGZsYWcgdG8gc2F5XG4gIC8vIHRoYXQgd2UncmUgYXdhaXRpbmcgYSAncmVhZGFibGUnIGV2ZW50IGVtaXNzaW9uLlxuICB0aGlzLm5lZWRSZWFkYWJsZSA9IGZhbHNlO1xuICB0aGlzLmVtaXR0ZWRSZWFkYWJsZSA9IGZhbHNlO1xuICB0aGlzLnJlYWRhYmxlTGlzdGVuaW5nID0gZmFsc2U7XG4gIHRoaXMucmVzdW1lU2NoZWR1bGVkID0gZmFsc2U7XG5cbiAgLy8gaGFzIGl0IGJlZW4gZGVzdHJveWVkXG4gIHRoaXMuZGVzdHJveWVkID0gZmFsc2U7XG5cbiAgLy8gQ3J5cHRvIGlzIGtpbmQgb2Ygb2xkIGFuZCBjcnVzdHkuICBIaXN0b3JpY2FsbHksIGl0cyBkZWZhdWx0IHN0cmluZ1xuICAvLyBlbmNvZGluZyBpcyAnYmluYXJ5JyBzbyB3ZSBoYXZlIHRvIG1ha2UgdGhpcyBjb25maWd1cmFibGUuXG4gIC8vIEV2ZXJ5dGhpbmcgZWxzZSBpbiB0aGUgdW5pdmVyc2UgdXNlcyAndXRmOCcsIHRob3VnaC5cbiAgdGhpcy5kZWZhdWx0RW5jb2RpbmcgPSBvcHRpb25zLmRlZmF1bHRFbmNvZGluZyB8fCAndXRmOCc7XG5cbiAgLy8gdGhlIG51bWJlciBvZiB3cml0ZXJzIHRoYXQgYXJlIGF3YWl0aW5nIGEgZHJhaW4gZXZlbnQgaW4gLnBpcGUoKXNcbiAgdGhpcy5hd2FpdERyYWluID0gMDtcblxuICAvLyBpZiB0cnVlLCBhIG1heWJlUmVhZE1vcmUgaGFzIGJlZW4gc2NoZWR1bGVkXG4gIHRoaXMucmVhZGluZ01vcmUgPSBmYWxzZTtcblxuICB0aGlzLmRlY29kZXIgPSBudWxsO1xuICB0aGlzLmVuY29kaW5nID0gbnVsbDtcbiAgaWYgKG9wdGlvbnMuZW5jb2RpbmcpIHtcbiAgICBpZiAoIVN0cmluZ0RlY29kZXIpIFN0cmluZ0RlY29kZXIgPSByZXF1aXJlKCdzdHJpbmdfZGVjb2Rlci8nKS5TdHJpbmdEZWNvZGVyO1xuICAgIHRoaXMuZGVjb2RlciA9IG5ldyBTdHJpbmdEZWNvZGVyKG9wdGlvbnMuZW5jb2RpbmcpO1xuICAgIHRoaXMuZW5jb2RpbmcgPSBvcHRpb25zLmVuY29kaW5nO1xuICB9XG59XG5cbmZ1bmN0aW9uIFJlYWRhYmxlKG9wdGlvbnMpIHtcbiAgRHVwbGV4ID0gRHVwbGV4IHx8IHJlcXVpcmUoJy4vX3N0cmVhbV9kdXBsZXgnKTtcblxuICBpZiAoISh0aGlzIGluc3RhbmNlb2YgUmVhZGFibGUpKSByZXR1cm4gbmV3IFJlYWRhYmxlKG9wdGlvbnMpO1xuXG4gIHRoaXMuX3JlYWRhYmxlU3RhdGUgPSBuZXcgUmVhZGFibGVTdGF0ZShvcHRpb25zLCB0aGlzKTtcblxuICAvLyBsZWdhY3lcbiAgdGhpcy5yZWFkYWJsZSA9IHRydWU7XG5cbiAgaWYgKG9wdGlvbnMpIHtcbiAgICBpZiAodHlwZW9mIG9wdGlvbnMucmVhZCA9PT0gJ2Z1bmN0aW9uJykgdGhpcy5fcmVhZCA9IG9wdGlvbnMucmVhZDtcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5kZXN0cm95ID09PSAnZnVuY3Rpb24nKSB0aGlzLl9kZXN0cm95ID0gb3B0aW9ucy5kZXN0cm95O1xuICB9XG5cbiAgU3RyZWFtLmNhbGwodGhpcyk7XG59XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWFkYWJsZS5wcm90b3R5cGUsICdkZXN0cm95ZWQnLCB7XG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIGlmICh0aGlzLl9yZWFkYWJsZVN0YXRlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RhdGUuZGVzdHJveWVkO1xuICB9LFxuICBzZXQ6IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgIC8vIHdlIGlnbm9yZSB0aGUgdmFsdWUgaWYgdGhlIHN0cmVhbVxuICAgIC8vIGhhcyBub3QgYmVlbiBpbml0aWFsaXplZCB5ZXRcbiAgICBpZiAoIXRoaXMuX3JlYWRhYmxlU3RhdGUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LCB0aGUgdXNlciBpcyBleHBsaWNpdGx5XG4gICAgLy8gbWFuYWdpbmcgZGVzdHJveWVkXG4gICAgdGhpcy5fcmVhZGFibGVTdGF0ZS5kZXN0cm95ZWQgPSB2YWx1ZTtcbiAgfVxufSk7XG5cblJlYWRhYmxlLnByb3RvdHlwZS5kZXN0cm95ID0gZGVzdHJveUltcGwuZGVzdHJveTtcblJlYWRhYmxlLnByb3RvdHlwZS5fdW5kZXN0cm95ID0gZGVzdHJveUltcGwudW5kZXN0cm95O1xuUmVhZGFibGUucHJvdG90eXBlLl9kZXN0cm95ID0gZnVuY3Rpb24gKGVyciwgY2IpIHtcbiAgdGhpcy5wdXNoKG51bGwpO1xuICBjYihlcnIpO1xufTtcblxuLy8gTWFudWFsbHkgc2hvdmUgc29tZXRoaW5nIGludG8gdGhlIHJlYWQoKSBidWZmZXIuXG4vLyBUaGlzIHJldHVybnMgdHJ1ZSBpZiB0aGUgaGlnaFdhdGVyTWFyayBoYXMgbm90IGJlZW4gaGl0IHlldCxcbi8vIHNpbWlsYXIgdG8gaG93IFdyaXRhYmxlLndyaXRlKCkgcmV0dXJucyB0cnVlIGlmIHlvdSBzaG91bGRcbi8vIHdyaXRlKCkgc29tZSBtb3JlLlxuUmVhZGFibGUucHJvdG90eXBlLnB1c2ggPSBmdW5jdGlvbiAoY2h1bmssIGVuY29kaW5nKSB7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG4gIHZhciBza2lwQ2h1bmtDaGVjaztcblxuICBpZiAoIXN0YXRlLm9iamVjdE1vZGUpIHtcbiAgICBpZiAodHlwZW9mIGNodW5rID09PSAnc3RyaW5nJykge1xuICAgICAgZW5jb2RpbmcgPSBlbmNvZGluZyB8fCBzdGF0ZS5kZWZhdWx0RW5jb2Rpbmc7XG4gICAgICBpZiAoZW5jb2RpbmcgIT09IHN0YXRlLmVuY29kaW5nKSB7XG4gICAgICAgIGNodW5rID0gQnVmZmVyLmZyb20oY2h1bmssIGVuY29kaW5nKTtcbiAgICAgICAgZW5jb2RpbmcgPSAnJztcbiAgICAgIH1cbiAgICAgIHNraXBDaHVua0NoZWNrID0gdHJ1ZTtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgc2tpcENodW5rQ2hlY2sgPSB0cnVlO1xuICB9XG5cbiAgcmV0dXJuIHJlYWRhYmxlQWRkQ2h1bmsodGhpcywgY2h1bmssIGVuY29kaW5nLCBmYWxzZSwgc2tpcENodW5rQ2hlY2spO1xufTtcblxuLy8gVW5zaGlmdCBzaG91bGQgKmFsd2F5cyogYmUgc29tZXRoaW5nIGRpcmVjdGx5IG91dCBvZiByZWFkKClcblJlYWRhYmxlLnByb3RvdHlwZS51bnNoaWZ0ID0gZnVuY3Rpb24gKGNodW5rKSB7XG4gIHJldHVybiByZWFkYWJsZUFkZENodW5rKHRoaXMsIGNodW5rLCBudWxsLCB0cnVlLCBmYWxzZSk7XG59O1xuXG5mdW5jdGlvbiByZWFkYWJsZUFkZENodW5rKHN0cmVhbSwgY2h1bmssIGVuY29kaW5nLCBhZGRUb0Zyb250LCBza2lwQ2h1bmtDaGVjaykge1xuICB2YXIgc3RhdGUgPSBzdHJlYW0uX3JlYWRhYmxlU3RhdGU7XG4gIGlmIChjaHVuayA9PT0gbnVsbCkge1xuICAgIHN0YXRlLnJlYWRpbmcgPSBmYWxzZTtcbiAgICBvbkVvZkNodW5rKHN0cmVhbSwgc3RhdGUpO1xuICB9IGVsc2Uge1xuICAgIHZhciBlcjtcbiAgICBpZiAoIXNraXBDaHVua0NoZWNrKSBlciA9IGNodW5rSW52YWxpZChzdGF0ZSwgY2h1bmspO1xuICAgIGlmIChlcikge1xuICAgICAgc3RyZWFtLmVtaXQoJ2Vycm9yJywgZXIpO1xuICAgIH0gZWxzZSBpZiAoc3RhdGUub2JqZWN0TW9kZSB8fCBjaHVuayAmJiBjaHVuay5sZW5ndGggPiAwKSB7XG4gICAgICBpZiAodHlwZW9mIGNodW5rICE9PSAnc3RyaW5nJyAmJiAhc3RhdGUub2JqZWN0TW9kZSAmJiBPYmplY3QuZ2V0UHJvdG90eXBlT2YoY2h1bmspICE9PSBCdWZmZXIucHJvdG90eXBlKSB7XG4gICAgICAgIGNodW5rID0gX3VpbnQ4QXJyYXlUb0J1ZmZlcihjaHVuayk7XG4gICAgICB9XG5cbiAgICAgIGlmIChhZGRUb0Zyb250KSB7XG4gICAgICAgIGlmIChzdGF0ZS5lbmRFbWl0dGVkKSBzdHJlYW0uZW1pdCgnZXJyb3InLCBuZXcgRXJyb3IoJ3N0cmVhbS51bnNoaWZ0KCkgYWZ0ZXIgZW5kIGV2ZW50JykpO2Vsc2UgYWRkQ2h1bmsoc3RyZWFtLCBzdGF0ZSwgY2h1bmssIHRydWUpO1xuICAgICAgfSBlbHNlIGlmIChzdGF0ZS5lbmRlZCkge1xuICAgICAgICBzdHJlYW0uZW1pdCgnZXJyb3InLCBuZXcgRXJyb3IoJ3N0cmVhbS5wdXNoKCkgYWZ0ZXIgRU9GJykpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RhdGUucmVhZGluZyA9IGZhbHNlO1xuICAgICAgICBpZiAoc3RhdGUuZGVjb2RlciAmJiAhZW5jb2RpbmcpIHtcbiAgICAgICAgICBjaHVuayA9IHN0YXRlLmRlY29kZXIud3JpdGUoY2h1bmspO1xuICAgICAgICAgIGlmIChzdGF0ZS5vYmplY3RNb2RlIHx8IGNodW5rLmxlbmd0aCAhPT0gMCkgYWRkQ2h1bmsoc3RyZWFtLCBzdGF0ZSwgY2h1bmssIGZhbHNlKTtlbHNlIG1heWJlUmVhZE1vcmUoc3RyZWFtLCBzdGF0ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgYWRkQ2h1bmsoc3RyZWFtLCBzdGF0ZSwgY2h1bmssIGZhbHNlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoIWFkZFRvRnJvbnQpIHtcbiAgICAgIHN0YXRlLnJlYWRpbmcgPSBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbmVlZE1vcmVEYXRhKHN0YXRlKTtcbn1cblxuZnVuY3Rpb24gYWRkQ2h1bmsoc3RyZWFtLCBzdGF0ZSwgY2h1bmssIGFkZFRvRnJvbnQpIHtcbiAgaWYgKHN0YXRlLmZsb3dpbmcgJiYgc3RhdGUubGVuZ3RoID09PSAwICYmICFzdGF0ZS5zeW5jKSB7XG4gICAgc3RyZWFtLmVtaXQoJ2RhdGEnLCBjaHVuayk7XG4gICAgc3RyZWFtLnJlYWQoMCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gdXBkYXRlIHRoZSBidWZmZXIgaW5mby5cbiAgICBzdGF0ZS5sZW5ndGggKz0gc3RhdGUub2JqZWN0TW9kZSA/IDEgOiBjaHVuay5sZW5ndGg7XG4gICAgaWYgKGFkZFRvRnJvbnQpIHN0YXRlLmJ1ZmZlci51bnNoaWZ0KGNodW5rKTtlbHNlIHN0YXRlLmJ1ZmZlci5wdXNoKGNodW5rKTtcblxuICAgIGlmIChzdGF0ZS5uZWVkUmVhZGFibGUpIGVtaXRSZWFkYWJsZShzdHJlYW0pO1xuICB9XG4gIG1heWJlUmVhZE1vcmUoc3RyZWFtLCBzdGF0ZSk7XG59XG5cbmZ1bmN0aW9uIGNodW5rSW52YWxpZChzdGF0ZSwgY2h1bmspIHtcbiAgdmFyIGVyO1xuICBpZiAoIV9pc1VpbnQ4QXJyYXkoY2h1bmspICYmIHR5cGVvZiBjaHVuayAhPT0gJ3N0cmluZycgJiYgY2h1bmsgIT09IHVuZGVmaW5lZCAmJiAhc3RhdGUub2JqZWN0TW9kZSkge1xuICAgIGVyID0gbmV3IFR5cGVFcnJvcignSW52YWxpZCBub24tc3RyaW5nL2J1ZmZlciBjaHVuaycpO1xuICB9XG4gIHJldHVybiBlcjtcbn1cblxuLy8gaWYgaXQncyBwYXN0IHRoZSBoaWdoIHdhdGVyIG1hcmssIHdlIGNhbiBwdXNoIGluIHNvbWUgbW9yZS5cbi8vIEFsc28sIGlmIHdlIGhhdmUgbm8gZGF0YSB5ZXQsIHdlIGNhbiBzdGFuZCBzb21lXG4vLyBtb3JlIGJ5dGVzLiAgVGhpcyBpcyB0byB3b3JrIGFyb3VuZCBjYXNlcyB3aGVyZSBod209MCxcbi8vIHN1Y2ggYXMgdGhlIHJlcGwuICBBbHNvLCBpZiB0aGUgcHVzaCgpIHRyaWdnZXJlZCBhXG4vLyByZWFkYWJsZSBldmVudCwgYW5kIHRoZSB1c2VyIGNhbGxlZCByZWFkKGxhcmdlTnVtYmVyKSBzdWNoIHRoYXRcbi8vIG5lZWRSZWFkYWJsZSB3YXMgc2V0LCB0aGVuIHdlIG91Z2h0IHRvIHB1c2ggbW9yZSwgc28gdGhhdCBhbm90aGVyXG4vLyAncmVhZGFibGUnIGV2ZW50IHdpbGwgYmUgdHJpZ2dlcmVkLlxuZnVuY3Rpb24gbmVlZE1vcmVEYXRhKHN0YXRlKSB7XG4gIHJldHVybiAhc3RhdGUuZW5kZWQgJiYgKHN0YXRlLm5lZWRSZWFkYWJsZSB8fCBzdGF0ZS5sZW5ndGggPCBzdGF0ZS5oaWdoV2F0ZXJNYXJrIHx8IHN0YXRlLmxlbmd0aCA9PT0gMCk7XG59XG5cblJlYWRhYmxlLnByb3RvdHlwZS5pc1BhdXNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRoaXMuX3JlYWRhYmxlU3RhdGUuZmxvd2luZyA9PT0gZmFsc2U7XG59O1xuXG4vLyBiYWNrd2FyZHMgY29tcGF0aWJpbGl0eS5cblJlYWRhYmxlLnByb3RvdHlwZS5zZXRFbmNvZGluZyA9IGZ1bmN0aW9uIChlbmMpIHtcbiAgaWYgKCFTdHJpbmdEZWNvZGVyKSBTdHJpbmdEZWNvZGVyID0gcmVxdWlyZSgnc3RyaW5nX2RlY29kZXIvJykuU3RyaW5nRGVjb2RlcjtcbiAgdGhpcy5fcmVhZGFibGVTdGF0ZS5kZWNvZGVyID0gbmV3IFN0cmluZ0RlY29kZXIoZW5jKTtcbiAgdGhpcy5fcmVhZGFibGVTdGF0ZS5lbmNvZGluZyA9IGVuYztcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG4vLyBEb24ndCByYWlzZSB0aGUgaHdtID4gOE1CXG52YXIgTUFYX0hXTSA9IDB4ODAwMDAwO1xuZnVuY3Rpb24gY29tcHV0ZU5ld0hpZ2hXYXRlck1hcmsobikge1xuICBpZiAobiA+PSBNQVhfSFdNKSB7XG4gICAgbiA9IE1BWF9IV007XG4gIH0gZWxzZSB7XG4gICAgLy8gR2V0IHRoZSBuZXh0IGhpZ2hlc3QgcG93ZXIgb2YgMiB0byBwcmV2ZW50IGluY3JlYXNpbmcgaHdtIGV4Y2Vzc2l2ZWx5IGluXG4gICAgLy8gdGlueSBhbW91bnRzXG4gICAgbi0tO1xuICAgIG4gfD0gbiA+Pj4gMTtcbiAgICBuIHw9IG4gPj4+IDI7XG4gICAgbiB8PSBuID4+PiA0O1xuICAgIG4gfD0gbiA+Pj4gODtcbiAgICBuIHw9IG4gPj4+IDE2O1xuICAgIG4rKztcbiAgfVxuICByZXR1cm4gbjtcbn1cblxuLy8gVGhpcyBmdW5jdGlvbiBpcyBkZXNpZ25lZCB0byBiZSBpbmxpbmFibGUsIHNvIHBsZWFzZSB0YWtlIGNhcmUgd2hlbiBtYWtpbmdcbi8vIGNoYW5nZXMgdG8gdGhlIGZ1bmN0aW9uIGJvZHkuXG5mdW5jdGlvbiBob3dNdWNoVG9SZWFkKG4sIHN0YXRlKSB7XG4gIGlmIChuIDw9IDAgfHwgc3RhdGUubGVuZ3RoID09PSAwICYmIHN0YXRlLmVuZGVkKSByZXR1cm4gMDtcbiAgaWYgKHN0YXRlLm9iamVjdE1vZGUpIHJldHVybiAxO1xuICBpZiAobiAhPT0gbikge1xuICAgIC8vIE9ubHkgZmxvdyBvbmUgYnVmZmVyIGF0IGEgdGltZVxuICAgIGlmIChzdGF0ZS5mbG93aW5nICYmIHN0YXRlLmxlbmd0aCkgcmV0dXJuIHN0YXRlLmJ1ZmZlci5oZWFkLmRhdGEubGVuZ3RoO2Vsc2UgcmV0dXJuIHN0YXRlLmxlbmd0aDtcbiAgfVxuICAvLyBJZiB3ZSdyZSBhc2tpbmcgZm9yIG1vcmUgdGhhbiB0aGUgY3VycmVudCBod20sIHRoZW4gcmFpc2UgdGhlIGh3bS5cbiAgaWYgKG4gPiBzdGF0ZS5oaWdoV2F0ZXJNYXJrKSBzdGF0ZS5oaWdoV2F0ZXJNYXJrID0gY29tcHV0ZU5ld0hpZ2hXYXRlck1hcmsobik7XG4gIGlmIChuIDw9IHN0YXRlLmxlbmd0aCkgcmV0dXJuIG47XG4gIC8vIERvbid0IGhhdmUgZW5vdWdoXG4gIGlmICghc3RhdGUuZW5kZWQpIHtcbiAgICBzdGF0ZS5uZWVkUmVhZGFibGUgPSB0cnVlO1xuICAgIHJldHVybiAwO1xuICB9XG4gIHJldHVybiBzdGF0ZS5sZW5ndGg7XG59XG5cbi8vIHlvdSBjYW4gb3ZlcnJpZGUgZWl0aGVyIHRoaXMgbWV0aG9kLCBvciB0aGUgYXN5bmMgX3JlYWQobikgYmVsb3cuXG5SZWFkYWJsZS5wcm90b3R5cGUucmVhZCA9IGZ1bmN0aW9uIChuKSB7XG4gIGRlYnVnKCdyZWFkJywgbik7XG4gIG4gPSBwYXJzZUludChuLCAxMCk7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3JlYWRhYmxlU3RhdGU7XG4gIHZhciBuT3JpZyA9IG47XG5cbiAgaWYgKG4gIT09IDApIHN0YXRlLmVtaXR0ZWRSZWFkYWJsZSA9IGZhbHNlO1xuXG4gIC8vIGlmIHdlJ3JlIGRvaW5nIHJlYWQoMCkgdG8gdHJpZ2dlciBhIHJlYWRhYmxlIGV2ZW50LCBidXQgd2VcbiAgLy8gYWxyZWFkeSBoYXZlIGEgYnVuY2ggb2YgZGF0YSBpbiB0aGUgYnVmZmVyLCB0aGVuIGp1c3QgdHJpZ2dlclxuICAvLyB0aGUgJ3JlYWRhYmxlJyBldmVudCBhbmQgbW92ZSBvbi5cbiAgaWYgKG4gPT09IDAgJiYgc3RhdGUubmVlZFJlYWRhYmxlICYmIChzdGF0ZS5sZW5ndGggPj0gc3RhdGUuaGlnaFdhdGVyTWFyayB8fCBzdGF0ZS5lbmRlZCkpIHtcbiAgICBkZWJ1ZygncmVhZDogZW1pdFJlYWRhYmxlJywgc3RhdGUubGVuZ3RoLCBzdGF0ZS5lbmRlZCk7XG4gICAgaWYgKHN0YXRlLmxlbmd0aCA9PT0gMCAmJiBzdGF0ZS5lbmRlZCkgZW5kUmVhZGFibGUodGhpcyk7ZWxzZSBlbWl0UmVhZGFibGUodGhpcyk7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBuID0gaG93TXVjaFRvUmVhZChuLCBzdGF0ZSk7XG5cbiAgLy8gaWYgd2UndmUgZW5kZWQsIGFuZCB3ZSdyZSBub3cgY2xlYXIsIHRoZW4gZmluaXNoIGl0IHVwLlxuICBpZiAobiA9PT0gMCAmJiBzdGF0ZS5lbmRlZCkge1xuICAgIGlmIChzdGF0ZS5sZW5ndGggPT09IDApIGVuZFJlYWRhYmxlKHRoaXMpO1xuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLy8gQWxsIHRoZSBhY3R1YWwgY2h1bmsgZ2VuZXJhdGlvbiBsb2dpYyBuZWVkcyB0byBiZVxuICAvLyAqYmVsb3cqIHRoZSBjYWxsIHRvIF9yZWFkLiAgVGhlIHJlYXNvbiBpcyB0aGF0IGluIGNlcnRhaW5cbiAgLy8gc3ludGhldGljIHN0cmVhbSBjYXNlcywgc3VjaCBhcyBwYXNzdGhyb3VnaCBzdHJlYW1zLCBfcmVhZFxuICAvLyBtYXkgYmUgYSBjb21wbGV0ZWx5IHN5bmNocm9ub3VzIG9wZXJhdGlvbiB3aGljaCBtYXkgY2hhbmdlXG4gIC8vIHRoZSBzdGF0ZSBvZiB0aGUgcmVhZCBidWZmZXIsIHByb3ZpZGluZyBlbm91Z2ggZGF0YSB3aGVuXG4gIC8vIGJlZm9yZSB0aGVyZSB3YXMgKm5vdCogZW5vdWdoLlxuICAvL1xuICAvLyBTbywgdGhlIHN0ZXBzIGFyZTpcbiAgLy8gMS4gRmlndXJlIG91dCB3aGF0IHRoZSBzdGF0ZSBvZiB0aGluZ3Mgd2lsbCBiZSBhZnRlciB3ZSBkb1xuICAvLyBhIHJlYWQgZnJvbSB0aGUgYnVmZmVyLlxuICAvL1xuICAvLyAyLiBJZiB0aGF0IHJlc3VsdGluZyBzdGF0ZSB3aWxsIHRyaWdnZXIgYSBfcmVhZCwgdGhlbiBjYWxsIF9yZWFkLlxuICAvLyBOb3RlIHRoYXQgdGhpcyBtYXkgYmUgYXN5bmNocm9ub3VzLCBvciBzeW5jaHJvbm91cy4gIFllcywgaXQgaXNcbiAgLy8gZGVlcGx5IHVnbHkgdG8gd3JpdGUgQVBJcyB0aGlzIHdheSwgYnV0IHRoYXQgc3RpbGwgZG9lc24ndCBtZWFuXG4gIC8vIHRoYXQgdGhlIFJlYWRhYmxlIGNsYXNzIHNob3VsZCBiZWhhdmUgaW1wcm9wZXJseSwgYXMgc3RyZWFtcyBhcmVcbiAgLy8gZGVzaWduZWQgdG8gYmUgc3luYy9hc3luYyBhZ25vc3RpYy5cbiAgLy8gVGFrZSBub3RlIGlmIHRoZSBfcmVhZCBjYWxsIGlzIHN5bmMgb3IgYXN5bmMgKGllLCBpZiB0aGUgcmVhZCBjYWxsXG4gIC8vIGhhcyByZXR1cm5lZCB5ZXQpLCBzbyB0aGF0IHdlIGtub3cgd2hldGhlciBvciBub3QgaXQncyBzYWZlIHRvIGVtaXRcbiAgLy8gJ3JlYWRhYmxlJyBldGMuXG4gIC8vXG4gIC8vIDMuIEFjdHVhbGx5IHB1bGwgdGhlIHJlcXVlc3RlZCBjaHVua3Mgb3V0IG9mIHRoZSBidWZmZXIgYW5kIHJldHVybi5cblxuICAvLyBpZiB3ZSBuZWVkIGEgcmVhZGFibGUgZXZlbnQsIHRoZW4gd2UgbmVlZCB0byBkbyBzb21lIHJlYWRpbmcuXG4gIHZhciBkb1JlYWQgPSBzdGF0ZS5uZWVkUmVhZGFibGU7XG4gIGRlYnVnKCduZWVkIHJlYWRhYmxlJywgZG9SZWFkKTtcblxuICAvLyBpZiB3ZSBjdXJyZW50bHkgaGF2ZSBsZXNzIHRoYW4gdGhlIGhpZ2hXYXRlck1hcmssIHRoZW4gYWxzbyByZWFkIHNvbWVcbiAgaWYgKHN0YXRlLmxlbmd0aCA9PT0gMCB8fCBzdGF0ZS5sZW5ndGggLSBuIDwgc3RhdGUuaGlnaFdhdGVyTWFyaykge1xuICAgIGRvUmVhZCA9IHRydWU7XG4gICAgZGVidWcoJ2xlbmd0aCBsZXNzIHRoYW4gd2F0ZXJtYXJrJywgZG9SZWFkKTtcbiAgfVxuXG4gIC8vIGhvd2V2ZXIsIGlmIHdlJ3ZlIGVuZGVkLCB0aGVuIHRoZXJlJ3Mgbm8gcG9pbnQsIGFuZCBpZiB3ZSdyZSBhbHJlYWR5XG4gIC8vIHJlYWRpbmcsIHRoZW4gaXQncyB1bm5lY2Vzc2FyeS5cbiAgaWYgKHN0YXRlLmVuZGVkIHx8IHN0YXRlLnJlYWRpbmcpIHtcbiAgICBkb1JlYWQgPSBmYWxzZTtcbiAgICBkZWJ1ZygncmVhZGluZyBvciBlbmRlZCcsIGRvUmVhZCk7XG4gIH0gZWxzZSBpZiAoZG9SZWFkKSB7XG4gICAgZGVidWcoJ2RvIHJlYWQnKTtcbiAgICBzdGF0ZS5yZWFkaW5nID0gdHJ1ZTtcbiAgICBzdGF0ZS5zeW5jID0gdHJ1ZTtcbiAgICAvLyBpZiB0aGUgbGVuZ3RoIGlzIGN1cnJlbnRseSB6ZXJvLCB0aGVuIHdlICpuZWVkKiBhIHJlYWRhYmxlIGV2ZW50LlxuICAgIGlmIChzdGF0ZS5sZW5ndGggPT09IDApIHN0YXRlLm5lZWRSZWFkYWJsZSA9IHRydWU7XG4gICAgLy8gY2FsbCBpbnRlcm5hbCByZWFkIG1ldGhvZFxuICAgIHRoaXMuX3JlYWQoc3RhdGUuaGlnaFdhdGVyTWFyayk7XG4gICAgc3RhdGUuc3luYyA9IGZhbHNlO1xuICAgIC8vIElmIF9yZWFkIHB1c2hlZCBkYXRhIHN5bmNocm9ub3VzbHksIHRoZW4gYHJlYWRpbmdgIHdpbGwgYmUgZmFsc2UsXG4gICAgLy8gYW5kIHdlIG5lZWQgdG8gcmUtZXZhbHVhdGUgaG93IG11Y2ggZGF0YSB3ZSBjYW4gcmV0dXJuIHRvIHRoZSB1c2VyLlxuICAgIGlmICghc3RhdGUucmVhZGluZykgbiA9IGhvd011Y2hUb1JlYWQobk9yaWcsIHN0YXRlKTtcbiAgfVxuXG4gIHZhciByZXQ7XG4gIGlmIChuID4gMCkgcmV0ID0gZnJvbUxpc3Qobiwgc3RhdGUpO2Vsc2UgcmV0ID0gbnVsbDtcblxuICBpZiAocmV0ID09PSBudWxsKSB7XG4gICAgc3RhdGUubmVlZFJlYWRhYmxlID0gdHJ1ZTtcbiAgICBuID0gMDtcbiAgfSBlbHNlIHtcbiAgICBzdGF0ZS5sZW5ndGggLT0gbjtcbiAgfVxuXG4gIGlmIChzdGF0ZS5sZW5ndGggPT09IDApIHtcbiAgICAvLyBJZiB3ZSBoYXZlIG5vdGhpbmcgaW4gdGhlIGJ1ZmZlciwgdGhlbiB3ZSB3YW50IHRvIGtub3dcbiAgICAvLyBhcyBzb29uIGFzIHdlICpkbyogZ2V0IHNvbWV0aGluZyBpbnRvIHRoZSBidWZmZXIuXG4gICAgaWYgKCFzdGF0ZS5lbmRlZCkgc3RhdGUubmVlZFJlYWRhYmxlID0gdHJ1ZTtcblxuICAgIC8vIElmIHdlIHRyaWVkIHRvIHJlYWQoKSBwYXN0IHRoZSBFT0YsIHRoZW4gZW1pdCBlbmQgb24gdGhlIG5leHQgdGljay5cbiAgICBpZiAobk9yaWcgIT09IG4gJiYgc3RhdGUuZW5kZWQpIGVuZFJlYWRhYmxlKHRoaXMpO1xuICB9XG5cbiAgaWYgKHJldCAhPT0gbnVsbCkgdGhpcy5lbWl0KCdkYXRhJywgcmV0KTtcblxuICByZXR1cm4gcmV0O1xufTtcblxuZnVuY3Rpb24gb25Fb2ZDaHVuayhzdHJlYW0sIHN0YXRlKSB7XG4gIGlmIChzdGF0ZS5lbmRlZCkgcmV0dXJuO1xuICBpZiAoc3RhdGUuZGVjb2Rlcikge1xuICAgIHZhciBjaHVuayA9IHN0YXRlLmRlY29kZXIuZW5kKCk7XG4gICAgaWYgKGNodW5rICYmIGNodW5rLmxlbmd0aCkge1xuICAgICAgc3RhdGUuYnVmZmVyLnB1c2goY2h1bmspO1xuICAgICAgc3RhdGUubGVuZ3RoICs9IHN0YXRlLm9iamVjdE1vZGUgPyAxIDogY2h1bmsubGVuZ3RoO1xuICAgIH1cbiAgfVxuICBzdGF0ZS5lbmRlZCA9IHRydWU7XG5cbiAgLy8gZW1pdCAncmVhZGFibGUnIG5vdyB0byBtYWtlIHN1cmUgaXQgZ2V0cyBwaWNrZWQgdXAuXG4gIGVtaXRSZWFkYWJsZShzdHJlYW0pO1xufVxuXG4vLyBEb24ndCBlbWl0IHJlYWRhYmxlIHJpZ2h0IGF3YXkgaW4gc3luYyBtb2RlLCBiZWNhdXNlIHRoaXMgY2FuIHRyaWdnZXJcbi8vIGFub3RoZXIgcmVhZCgpIGNhbGwgPT4gc3RhY2sgb3ZlcmZsb3cuICBUaGlzIHdheSwgaXQgbWlnaHQgdHJpZ2dlclxuLy8gYSBuZXh0VGljayByZWN1cnNpb24gd2FybmluZywgYnV0IHRoYXQncyBub3Qgc28gYmFkLlxuZnVuY3Rpb24gZW1pdFJlYWRhYmxlKHN0cmVhbSkge1xuICB2YXIgc3RhdGUgPSBzdHJlYW0uX3JlYWRhYmxlU3RhdGU7XG4gIHN0YXRlLm5lZWRSZWFkYWJsZSA9IGZhbHNlO1xuICBpZiAoIXN0YXRlLmVtaXR0ZWRSZWFkYWJsZSkge1xuICAgIGRlYnVnKCdlbWl0UmVhZGFibGUnLCBzdGF0ZS5mbG93aW5nKTtcbiAgICBzdGF0ZS5lbWl0dGVkUmVhZGFibGUgPSB0cnVlO1xuICAgIGlmIChzdGF0ZS5zeW5jKSBwbmEubmV4dFRpY2soZW1pdFJlYWRhYmxlXywgc3RyZWFtKTtlbHNlIGVtaXRSZWFkYWJsZV8oc3RyZWFtKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBlbWl0UmVhZGFibGVfKHN0cmVhbSkge1xuICBkZWJ1ZygnZW1pdCByZWFkYWJsZScpO1xuICBzdHJlYW0uZW1pdCgncmVhZGFibGUnKTtcbiAgZmxvdyhzdHJlYW0pO1xufVxuXG4vLyBhdCB0aGlzIHBvaW50LCB0aGUgdXNlciBoYXMgcHJlc3VtYWJseSBzZWVuIHRoZSAncmVhZGFibGUnIGV2ZW50LFxuLy8gYW5kIGNhbGxlZCByZWFkKCkgdG8gY29uc3VtZSBzb21lIGRhdGEuICB0aGF0IG1heSBoYXZlIHRyaWdnZXJlZFxuLy8gaW4gdHVybiBhbm90aGVyIF9yZWFkKG4pIGNhbGwsIGluIHdoaWNoIGNhc2UgcmVhZGluZyA9IHRydWUgaWZcbi8vIGl0J3MgaW4gcHJvZ3Jlc3MuXG4vLyBIb3dldmVyLCBpZiB3ZSdyZSBub3QgZW5kZWQsIG9yIHJlYWRpbmcsIGFuZCB0aGUgbGVuZ3RoIDwgaHdtLFxuLy8gdGhlbiBnbyBhaGVhZCBhbmQgdHJ5IHRvIHJlYWQgc29tZSBtb3JlIHByZWVtcHRpdmVseS5cbmZ1bmN0aW9uIG1heWJlUmVhZE1vcmUoc3RyZWFtLCBzdGF0ZSkge1xuICBpZiAoIXN0YXRlLnJlYWRpbmdNb3JlKSB7XG4gICAgc3RhdGUucmVhZGluZ01vcmUgPSB0cnVlO1xuICAgIHBuYS5uZXh0VGljayhtYXliZVJlYWRNb3JlXywgc3RyZWFtLCBzdGF0ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF5YmVSZWFkTW9yZV8oc3RyZWFtLCBzdGF0ZSkge1xuICB2YXIgbGVuID0gc3RhdGUubGVuZ3RoO1xuICB3aGlsZSAoIXN0YXRlLnJlYWRpbmcgJiYgIXN0YXRlLmZsb3dpbmcgJiYgIXN0YXRlLmVuZGVkICYmIHN0YXRlLmxlbmd0aCA8IHN0YXRlLmhpZ2hXYXRlck1hcmspIHtcbiAgICBkZWJ1ZygnbWF5YmVSZWFkTW9yZSByZWFkIDAnKTtcbiAgICBzdHJlYW0ucmVhZCgwKTtcbiAgICBpZiAobGVuID09PSBzdGF0ZS5sZW5ndGgpXG4gICAgICAvLyBkaWRuJ3QgZ2V0IGFueSBkYXRhLCBzdG9wIHNwaW5uaW5nLlxuICAgICAgYnJlYWs7ZWxzZSBsZW4gPSBzdGF0ZS5sZW5ndGg7XG4gIH1cbiAgc3RhdGUucmVhZGluZ01vcmUgPSBmYWxzZTtcbn1cblxuLy8gYWJzdHJhY3QgbWV0aG9kLiAgdG8gYmUgb3ZlcnJpZGRlbiBpbiBzcGVjaWZpYyBpbXBsZW1lbnRhdGlvbiBjbGFzc2VzLlxuLy8gY2FsbCBjYihlciwgZGF0YSkgd2hlcmUgZGF0YSBpcyA8PSBuIGluIGxlbmd0aC5cbi8vIGZvciB2aXJ0dWFsIChub24tc3RyaW5nLCBub24tYnVmZmVyKSBzdHJlYW1zLCBcImxlbmd0aFwiIGlzIHNvbWV3aGF0XG4vLyBhcmJpdHJhcnksIGFuZCBwZXJoYXBzIG5vdCB2ZXJ5IG1lYW5pbmdmdWwuXG5SZWFkYWJsZS5wcm90b3R5cGUuX3JlYWQgPSBmdW5jdGlvbiAobikge1xuICB0aGlzLmVtaXQoJ2Vycm9yJywgbmV3IEVycm9yKCdfcmVhZCgpIGlzIG5vdCBpbXBsZW1lbnRlZCcpKTtcbn07XG5cblJlYWRhYmxlLnByb3RvdHlwZS5waXBlID0gZnVuY3Rpb24gKGRlc3QsIHBpcGVPcHRzKSB7XG4gIHZhciBzcmMgPSB0aGlzO1xuICB2YXIgc3RhdGUgPSB0aGlzLl9yZWFkYWJsZVN0YXRlO1xuXG4gIHN3aXRjaCAoc3RhdGUucGlwZXNDb3VudCkge1xuICAgIGNhc2UgMDpcbiAgICAgIHN0YXRlLnBpcGVzID0gZGVzdDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgMTpcbiAgICAgIHN0YXRlLnBpcGVzID0gW3N0YXRlLnBpcGVzLCBkZXN0XTtcbiAgICAgIGJyZWFrO1xuICAgIGRlZmF1bHQ6XG4gICAgICBzdGF0ZS5waXBlcy5wdXNoKGRlc3QpO1xuICAgICAgYnJlYWs7XG4gIH1cbiAgc3RhdGUucGlwZXNDb3VudCArPSAxO1xuICBkZWJ1ZygncGlwZSBjb3VudD0lZCBvcHRzPSVqJywgc3RhdGUucGlwZXNDb3VudCwgcGlwZU9wdHMpO1xuXG4gIHZhciBkb0VuZCA9ICghcGlwZU9wdHMgfHwgcGlwZU9wdHMuZW5kICE9PSBmYWxzZSkgJiYgZGVzdCAhPT0gcHJvY2Vzcy5zdGRvdXQgJiYgZGVzdCAhPT0gcHJvY2Vzcy5zdGRlcnI7XG5cbiAgdmFyIGVuZEZuID0gZG9FbmQgPyBvbmVuZCA6IHVucGlwZTtcbiAgaWYgKHN0YXRlLmVuZEVtaXR0ZWQpIHBuYS5uZXh0VGljayhlbmRGbik7ZWxzZSBzcmMub25jZSgnZW5kJywgZW5kRm4pO1xuXG4gIGRlc3Qub24oJ3VucGlwZScsIG9udW5waXBlKTtcbiAgZnVuY3Rpb24gb251bnBpcGUocmVhZGFibGUsIHVucGlwZUluZm8pIHtcbiAgICBkZWJ1Zygnb251bnBpcGUnKTtcbiAgICBpZiAocmVhZGFibGUgPT09IHNyYykge1xuICAgICAgaWYgKHVucGlwZUluZm8gJiYgdW5waXBlSW5mby5oYXNVbnBpcGVkID09PSBmYWxzZSkge1xuICAgICAgICB1bnBpcGVJbmZvLmhhc1VucGlwZWQgPSB0cnVlO1xuICAgICAgICBjbGVhbnVwKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gb25lbmQoKSB7XG4gICAgZGVidWcoJ29uZW5kJyk7XG4gICAgZGVzdC5lbmQoKTtcbiAgfVxuXG4gIC8vIHdoZW4gdGhlIGRlc3QgZHJhaW5zLCBpdCByZWR1Y2VzIHRoZSBhd2FpdERyYWluIGNvdW50ZXJcbiAgLy8gb24gdGhlIHNvdXJjZS4gIFRoaXMgd291bGQgYmUgbW9yZSBlbGVnYW50IHdpdGggYSAub25jZSgpXG4gIC8vIGhhbmRsZXIgaW4gZmxvdygpLCBidXQgYWRkaW5nIGFuZCByZW1vdmluZyByZXBlYXRlZGx5IGlzXG4gIC8vIHRvbyBzbG93LlxuICB2YXIgb25kcmFpbiA9IHBpcGVPbkRyYWluKHNyYyk7XG4gIGRlc3Qub24oJ2RyYWluJywgb25kcmFpbik7XG5cbiAgdmFyIGNsZWFuZWRVcCA9IGZhbHNlO1xuICBmdW5jdGlvbiBjbGVhbnVwKCkge1xuICAgIGRlYnVnKCdjbGVhbnVwJyk7XG4gICAgLy8gY2xlYW51cCBldmVudCBoYW5kbGVycyBvbmNlIHRoZSBwaXBlIGlzIGJyb2tlblxuICAgIGRlc3QucmVtb3ZlTGlzdGVuZXIoJ2Nsb3NlJywgb25jbG9zZSk7XG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignZmluaXNoJywgb25maW5pc2gpO1xuICAgIGRlc3QucmVtb3ZlTGlzdGVuZXIoJ2RyYWluJywgb25kcmFpbik7XG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignZXJyb3InLCBvbmVycm9yKTtcbiAgICBkZXN0LnJlbW92ZUxpc3RlbmVyKCd1bnBpcGUnLCBvbnVucGlwZSk7XG4gICAgc3JjLnJlbW92ZUxpc3RlbmVyKCdlbmQnLCBvbmVuZCk7XG4gICAgc3JjLnJlbW92ZUxpc3RlbmVyKCdlbmQnLCB1bnBpcGUpO1xuICAgIHNyYy5yZW1vdmVMaXN0ZW5lcignZGF0YScsIG9uZGF0YSk7XG5cbiAgICBjbGVhbmVkVXAgPSB0cnVlO1xuXG4gICAgLy8gaWYgdGhlIHJlYWRlciBpcyB3YWl0aW5nIGZvciBhIGRyYWluIGV2ZW50IGZyb20gdGhpc1xuICAgIC8vIHNwZWNpZmljIHdyaXRlciwgdGhlbiBpdCB3b3VsZCBjYXVzZSBpdCB0byBuZXZlciBzdGFydFxuICAgIC8vIGZsb3dpbmcgYWdhaW4uXG4gICAgLy8gU28sIGlmIHRoaXMgaXMgYXdhaXRpbmcgYSBkcmFpbiwgdGhlbiB3ZSBqdXN0IGNhbGwgaXQgbm93LlxuICAgIC8vIElmIHdlIGRvbid0IGtub3csIHRoZW4gYXNzdW1lIHRoYXQgd2UgYXJlIHdhaXRpbmcgZm9yIG9uZS5cbiAgICBpZiAoc3RhdGUuYXdhaXREcmFpbiAmJiAoIWRlc3QuX3dyaXRhYmxlU3RhdGUgfHwgZGVzdC5fd3JpdGFibGVTdGF0ZS5uZWVkRHJhaW4pKSBvbmRyYWluKCk7XG4gIH1cblxuICAvLyBJZiB0aGUgdXNlciBwdXNoZXMgbW9yZSBkYXRhIHdoaWxlIHdlJ3JlIHdyaXRpbmcgdG8gZGVzdCB0aGVuIHdlJ2xsIGVuZCB1cFxuICAvLyBpbiBvbmRhdGEgYWdhaW4uIEhvd2V2ZXIsIHdlIG9ubHkgd2FudCB0byBpbmNyZWFzZSBhd2FpdERyYWluIG9uY2UgYmVjYXVzZVxuICAvLyBkZXN0IHdpbGwgb25seSBlbWl0IG9uZSAnZHJhaW4nIGV2ZW50IGZvciB0aGUgbXVsdGlwbGUgd3JpdGVzLlxuICAvLyA9PiBJbnRyb2R1Y2UgYSBndWFyZCBvbiBpbmNyZWFzaW5nIGF3YWl0RHJhaW4uXG4gIHZhciBpbmNyZWFzZWRBd2FpdERyYWluID0gZmFsc2U7XG4gIHNyYy5vbignZGF0YScsIG9uZGF0YSk7XG4gIGZ1bmN0aW9uIG9uZGF0YShjaHVuaykge1xuICAgIGRlYnVnKCdvbmRhdGEnKTtcbiAgICBpbmNyZWFzZWRBd2FpdERyYWluID0gZmFsc2U7XG4gICAgdmFyIHJldCA9IGRlc3Qud3JpdGUoY2h1bmspO1xuICAgIGlmIChmYWxzZSA9PT0gcmV0ICYmICFpbmNyZWFzZWRBd2FpdERyYWluKSB7XG4gICAgICAvLyBJZiB0aGUgdXNlciB1bnBpcGVkIGR1cmluZyBgZGVzdC53cml0ZSgpYCwgaXQgaXMgcG9zc2libGVcbiAgICAgIC8vIHRvIGdldCBzdHVjayBpbiBhIHBlcm1hbmVudGx5IHBhdXNlZCBzdGF0ZSBpZiB0aGF0IHdyaXRlXG4gICAgICAvLyBhbHNvIHJldHVybmVkIGZhbHNlLlxuICAgICAgLy8gPT4gQ2hlY2sgd2hldGhlciBgZGVzdGAgaXMgc3RpbGwgYSBwaXBpbmcgZGVzdGluYXRpb24uXG4gICAgICBpZiAoKHN0YXRlLnBpcGVzQ291bnQgPT09IDEgJiYgc3RhdGUucGlwZXMgPT09IGRlc3QgfHwgc3RhdGUucGlwZXNDb3VudCA+IDEgJiYgaW5kZXhPZihzdGF0ZS5waXBlcywgZGVzdCkgIT09IC0xKSAmJiAhY2xlYW5lZFVwKSB7XG4gICAgICAgIGRlYnVnKCdmYWxzZSB3cml0ZSByZXNwb25zZSwgcGF1c2UnLCBzcmMuX3JlYWRhYmxlU3RhdGUuYXdhaXREcmFpbik7XG4gICAgICAgIHNyYy5fcmVhZGFibGVTdGF0ZS5hd2FpdERyYWluKys7XG4gICAgICAgIGluY3JlYXNlZEF3YWl0RHJhaW4gPSB0cnVlO1xuICAgICAgfVxuICAgICAgc3JjLnBhdXNlKCk7XG4gICAgfVxuICB9XG5cbiAgLy8gaWYgdGhlIGRlc3QgaGFzIGFuIGVycm9yLCB0aGVuIHN0b3AgcGlwaW5nIGludG8gaXQuXG4gIC8vIGhvd2V2ZXIsIGRvbid0IHN1cHByZXNzIHRoZSB0aHJvd2luZyBiZWhhdmlvciBmb3IgdGhpcy5cbiAgZnVuY3Rpb24gb25lcnJvcihlcikge1xuICAgIGRlYnVnKCdvbmVycm9yJywgZXIpO1xuICAgIHVucGlwZSgpO1xuICAgIGRlc3QucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgb25lcnJvcik7XG4gICAgaWYgKEVFbGlzdGVuZXJDb3VudChkZXN0LCAnZXJyb3InKSA9PT0gMCkgZGVzdC5lbWl0KCdlcnJvcicsIGVyKTtcbiAgfVxuXG4gIC8vIE1ha2Ugc3VyZSBvdXIgZXJyb3IgaGFuZGxlciBpcyBhdHRhY2hlZCBiZWZvcmUgdXNlcmxhbmQgb25lcy5cbiAgcHJlcGVuZExpc3RlbmVyKGRlc3QsICdlcnJvcicsIG9uZXJyb3IpO1xuXG4gIC8vIEJvdGggY2xvc2UgYW5kIGZpbmlzaCBzaG91bGQgdHJpZ2dlciB1bnBpcGUsIGJ1dCBvbmx5IG9uY2UuXG4gIGZ1bmN0aW9uIG9uY2xvc2UoKSB7XG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignZmluaXNoJywgb25maW5pc2gpO1xuICAgIHVucGlwZSgpO1xuICB9XG4gIGRlc3Qub25jZSgnY2xvc2UnLCBvbmNsb3NlKTtcbiAgZnVuY3Rpb24gb25maW5pc2goKSB7XG4gICAgZGVidWcoJ29uZmluaXNoJyk7XG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignY2xvc2UnLCBvbmNsb3NlKTtcbiAgICB1bnBpcGUoKTtcbiAgfVxuICBkZXN0Lm9uY2UoJ2ZpbmlzaCcsIG9uZmluaXNoKTtcblxuICBmdW5jdGlvbiB1bnBpcGUoKSB7XG4gICAgZGVidWcoJ3VucGlwZScpO1xuICAgIHNyYy51bnBpcGUoZGVzdCk7XG4gIH1cblxuICAvLyB0ZWxsIHRoZSBkZXN0IHRoYXQgaXQncyBiZWluZyBwaXBlZCB0b1xuICBkZXN0LmVtaXQoJ3BpcGUnLCBzcmMpO1xuXG4gIC8vIHN0YXJ0IHRoZSBmbG93IGlmIGl0IGhhc24ndCBiZWVuIHN0YXJ0ZWQgYWxyZWFkeS5cbiAgaWYgKCFzdGF0ZS5mbG93aW5nKSB7XG4gICAgZGVidWcoJ3BpcGUgcmVzdW1lJyk7XG4gICAgc3JjLnJlc3VtZSgpO1xuICB9XG5cbiAgcmV0dXJuIGRlc3Q7XG59O1xuXG5mdW5jdGlvbiBwaXBlT25EcmFpbihzcmMpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgc3RhdGUgPSBzcmMuX3JlYWRhYmxlU3RhdGU7XG4gICAgZGVidWcoJ3BpcGVPbkRyYWluJywgc3RhdGUuYXdhaXREcmFpbik7XG4gICAgaWYgKHN0YXRlLmF3YWl0RHJhaW4pIHN0YXRlLmF3YWl0RHJhaW4tLTtcbiAgICBpZiAoc3RhdGUuYXdhaXREcmFpbiA9PT0gMCAmJiBFRWxpc3RlbmVyQ291bnQoc3JjLCAnZGF0YScpKSB7XG4gICAgICBzdGF0ZS5mbG93aW5nID0gdHJ1ZTtcbiAgICAgIGZsb3coc3JjKTtcbiAgICB9XG4gIH07XG59XG5cblJlYWRhYmxlLnByb3RvdHlwZS51bnBpcGUgPSBmdW5jdGlvbiAoZGVzdCkge1xuICB2YXIgc3RhdGUgPSB0aGlzLl9yZWFkYWJsZVN0YXRlO1xuICB2YXIgdW5waXBlSW5mbyA9IHsgaGFzVW5waXBlZDogZmFsc2UgfTtcblxuICAvLyBpZiB3ZSdyZSBub3QgcGlwaW5nIGFueXdoZXJlLCB0aGVuIGRvIG5vdGhpbmcuXG4gIGlmIChzdGF0ZS5waXBlc0NvdW50ID09PSAwKSByZXR1cm4gdGhpcztcblxuICAvLyBqdXN0IG9uZSBkZXN0aW5hdGlvbi4gIG1vc3QgY29tbW9uIGNhc2UuXG4gIGlmIChzdGF0ZS5waXBlc0NvdW50ID09PSAxKSB7XG4gICAgLy8gcGFzc2VkIGluIG9uZSwgYnV0IGl0J3Mgbm90IHRoZSByaWdodCBvbmUuXG4gICAgaWYgKGRlc3QgJiYgZGVzdCAhPT0gc3RhdGUucGlwZXMpIHJldHVybiB0aGlzO1xuXG4gICAgaWYgKCFkZXN0KSBkZXN0ID0gc3RhdGUucGlwZXM7XG5cbiAgICAvLyBnb3QgYSBtYXRjaC5cbiAgICBzdGF0ZS5waXBlcyA9IG51bGw7XG4gICAgc3RhdGUucGlwZXNDb3VudCA9IDA7XG4gICAgc3RhdGUuZmxvd2luZyA9IGZhbHNlO1xuICAgIGlmIChkZXN0KSBkZXN0LmVtaXQoJ3VucGlwZScsIHRoaXMsIHVucGlwZUluZm8pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gc2xvdyBjYXNlLiBtdWx0aXBsZSBwaXBlIGRlc3RpbmF0aW9ucy5cblxuICBpZiAoIWRlc3QpIHtcbiAgICAvLyByZW1vdmUgYWxsLlxuICAgIHZhciBkZXN0cyA9IHN0YXRlLnBpcGVzO1xuICAgIHZhciBsZW4gPSBzdGF0ZS5waXBlc0NvdW50O1xuICAgIHN0YXRlLnBpcGVzID0gbnVsbDtcbiAgICBzdGF0ZS5waXBlc0NvdW50ID0gMDtcbiAgICBzdGF0ZS5mbG93aW5nID0gZmFsc2U7XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGxlbjsgaSsrKSB7XG4gICAgICBkZXN0c1tpXS5lbWl0KCd1bnBpcGUnLCB0aGlzLCB1bnBpcGVJbmZvKTtcbiAgICB9cmV0dXJuIHRoaXM7XG4gIH1cblxuICAvLyB0cnkgdG8gZmluZCB0aGUgcmlnaHQgb25lLlxuICB2YXIgaW5kZXggPSBpbmRleE9mKHN0YXRlLnBpcGVzLCBkZXN0KTtcbiAgaWYgKGluZGV4ID09PSAtMSkgcmV0dXJuIHRoaXM7XG5cbiAgc3RhdGUucGlwZXMuc3BsaWNlKGluZGV4LCAxKTtcbiAgc3RhdGUucGlwZXNDb3VudCAtPSAxO1xuICBpZiAoc3RhdGUucGlwZXNDb3VudCA9PT0gMSkgc3RhdGUucGlwZXMgPSBzdGF0ZS5waXBlc1swXTtcblxuICBkZXN0LmVtaXQoJ3VucGlwZScsIHRoaXMsIHVucGlwZUluZm8pO1xuXG4gIHJldHVybiB0aGlzO1xufTtcblxuLy8gc2V0IHVwIGRhdGEgZXZlbnRzIGlmIHRoZXkgYXJlIGFza2VkIGZvclxuLy8gRW5zdXJlIHJlYWRhYmxlIGxpc3RlbmVycyBldmVudHVhbGx5IGdldCBzb21ldGhpbmdcblJlYWRhYmxlLnByb3RvdHlwZS5vbiA9IGZ1bmN0aW9uIChldiwgZm4pIHtcbiAgdmFyIHJlcyA9IFN0cmVhbS5wcm90b3R5cGUub24uY2FsbCh0aGlzLCBldiwgZm4pO1xuXG4gIGlmIChldiA9PT0gJ2RhdGEnKSB7XG4gICAgLy8gU3RhcnQgZmxvd2luZyBvbiBuZXh0IHRpY2sgaWYgc3RyZWFtIGlzbid0IGV4cGxpY2l0bHkgcGF1c2VkXG4gICAgaWYgKHRoaXMuX3JlYWRhYmxlU3RhdGUuZmxvd2luZyAhPT0gZmFsc2UpIHRoaXMucmVzdW1lKCk7XG4gIH0gZWxzZSBpZiAoZXYgPT09ICdyZWFkYWJsZScpIHtcbiAgICB2YXIgc3RhdGUgPSB0aGlzLl9yZWFkYWJsZVN0YXRlO1xuICAgIGlmICghc3RhdGUuZW5kRW1pdHRlZCAmJiAhc3RhdGUucmVhZGFibGVMaXN0ZW5pbmcpIHtcbiAgICAgIHN0YXRlLnJlYWRhYmxlTGlzdGVuaW5nID0gc3RhdGUubmVlZFJlYWRhYmxlID0gdHJ1ZTtcbiAgICAgIHN0YXRlLmVtaXR0ZWRSZWFkYWJsZSA9IGZhbHNlO1xuICAgICAgaWYgKCFzdGF0ZS5yZWFkaW5nKSB7XG4gICAgICAgIHBuYS5uZXh0VGljayhuUmVhZGluZ05leHRUaWNrLCB0aGlzKTtcbiAgICAgIH0gZWxzZSBpZiAoc3RhdGUubGVuZ3RoKSB7XG4gICAgICAgIGVtaXRSZWFkYWJsZSh0aGlzKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gcmVzO1xufTtcblJlYWRhYmxlLnByb3RvdHlwZS5hZGRMaXN0ZW5lciA9IFJlYWRhYmxlLnByb3RvdHlwZS5vbjtcblxuZnVuY3Rpb24gblJlYWRpbmdOZXh0VGljayhzZWxmKSB7XG4gIGRlYnVnKCdyZWFkYWJsZSBuZXh0dGljayByZWFkIDAnKTtcbiAgc2VsZi5yZWFkKDApO1xufVxuXG4vLyBwYXVzZSgpIGFuZCByZXN1bWUoKSBhcmUgcmVtbmFudHMgb2YgdGhlIGxlZ2FjeSByZWFkYWJsZSBzdHJlYW0gQVBJXG4vLyBJZiB0aGUgdXNlciB1c2VzIHRoZW0sIHRoZW4gc3dpdGNoIGludG8gb2xkIG1vZGUuXG5SZWFkYWJsZS5wcm90b3R5cGUucmVzdW1lID0gZnVuY3Rpb24gKCkge1xuICB2YXIgc3RhdGUgPSB0aGlzLl9yZWFkYWJsZVN0YXRlO1xuICBpZiAoIXN0YXRlLmZsb3dpbmcpIHtcbiAgICBkZWJ1ZygncmVzdW1lJyk7XG4gICAgc3RhdGUuZmxvd2luZyA9IHRydWU7XG4gICAgcmVzdW1lKHRoaXMsIHN0YXRlKTtcbiAgfVxuICByZXR1cm4gdGhpcztcbn07XG5cbmZ1bmN0aW9uIHJlc3VtZShzdHJlYW0sIHN0YXRlKSB7XG4gIGlmICghc3RhdGUucmVzdW1lU2NoZWR1bGVkKSB7XG4gICAgc3RhdGUucmVzdW1lU2NoZWR1bGVkID0gdHJ1ZTtcbiAgICBwbmEubmV4dFRpY2socmVzdW1lXywgc3RyZWFtLCBzdGF0ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVzdW1lXyhzdHJlYW0sIHN0YXRlKSB7XG4gIGlmICghc3RhdGUucmVhZGluZykge1xuICAgIGRlYnVnKCdyZXN1bWUgcmVhZCAwJyk7XG4gICAgc3RyZWFtLnJlYWQoMCk7XG4gIH1cblxuICBzdGF0ZS5yZXN1bWVTY2hlZHVsZWQgPSBmYWxzZTtcbiAgc3RhdGUuYXdhaXREcmFpbiA9IDA7XG4gIHN0cmVhbS5lbWl0KCdyZXN1bWUnKTtcbiAgZmxvdyhzdHJlYW0pO1xuICBpZiAoc3RhdGUuZmxvd2luZyAmJiAhc3RhdGUucmVhZGluZykgc3RyZWFtLnJlYWQoMCk7XG59XG5cblJlYWRhYmxlLnByb3RvdHlwZS5wYXVzZSA9IGZ1bmN0aW9uICgpIHtcbiAgZGVidWcoJ2NhbGwgcGF1c2UgZmxvd2luZz0laicsIHRoaXMuX3JlYWRhYmxlU3RhdGUuZmxvd2luZyk7XG4gIGlmIChmYWxzZSAhPT0gdGhpcy5fcmVhZGFibGVTdGF0ZS5mbG93aW5nKSB7XG4gICAgZGVidWcoJ3BhdXNlJyk7XG4gICAgdGhpcy5fcmVhZGFibGVTdGF0ZS5mbG93aW5nID0gZmFsc2U7XG4gICAgdGhpcy5lbWl0KCdwYXVzZScpO1xuICB9XG4gIHJldHVybiB0aGlzO1xufTtcblxuZnVuY3Rpb24gZmxvdyhzdHJlYW0pIHtcbiAgdmFyIHN0YXRlID0gc3RyZWFtLl9yZWFkYWJsZVN0YXRlO1xuICBkZWJ1ZygnZmxvdycsIHN0YXRlLmZsb3dpbmcpO1xuICB3aGlsZSAoc3RhdGUuZmxvd2luZyAmJiBzdHJlYW0ucmVhZCgpICE9PSBudWxsKSB7fVxufVxuXG4vLyB3cmFwIGFuIG9sZC1zdHlsZSBzdHJlYW0gYXMgdGhlIGFzeW5jIGRhdGEgc291cmNlLlxuLy8gVGhpcyBpcyAqbm90KiBwYXJ0IG9mIHRoZSByZWFkYWJsZSBzdHJlYW0gaW50ZXJmYWNlLlxuLy8gSXQgaXMgYW4gdWdseSB1bmZvcnR1bmF0ZSBtZXNzIG9mIGhpc3RvcnkuXG5SZWFkYWJsZS5wcm90b3R5cGUud3JhcCA9IGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgdmFyIF90aGlzID0gdGhpcztcblxuICB2YXIgc3RhdGUgPSB0aGlzLl9yZWFkYWJsZVN0YXRlO1xuICB2YXIgcGF1c2VkID0gZmFsc2U7XG5cbiAgc3RyZWFtLm9uKCdlbmQnLCBmdW5jdGlvbiAoKSB7XG4gICAgZGVidWcoJ3dyYXBwZWQgZW5kJyk7XG4gICAgaWYgKHN0YXRlLmRlY29kZXIgJiYgIXN0YXRlLmVuZGVkKSB7XG4gICAgICB2YXIgY2h1bmsgPSBzdGF0ZS5kZWNvZGVyLmVuZCgpO1xuICAgICAgaWYgKGNodW5rICYmIGNodW5rLmxlbmd0aCkgX3RoaXMucHVzaChjaHVuayk7XG4gICAgfVxuXG4gICAgX3RoaXMucHVzaChudWxsKTtcbiAgfSk7XG5cbiAgc3RyZWFtLm9uKCdkYXRhJywgZnVuY3Rpb24gKGNodW5rKSB7XG4gICAgZGVidWcoJ3dyYXBwZWQgZGF0YScpO1xuICAgIGlmIChzdGF0ZS5kZWNvZGVyKSBjaHVuayA9IHN0YXRlLmRlY29kZXIud3JpdGUoY2h1bmspO1xuXG4gICAgLy8gZG9uJ3Qgc2tpcCBvdmVyIGZhbHN5IHZhbHVlcyBpbiBvYmplY3RNb2RlXG4gICAgaWYgKHN0YXRlLm9iamVjdE1vZGUgJiYgKGNodW5rID09PSBudWxsIHx8IGNodW5rID09PSB1bmRlZmluZWQpKSByZXR1cm47ZWxzZSBpZiAoIXN0YXRlLm9iamVjdE1vZGUgJiYgKCFjaHVuayB8fCAhY2h1bmsubGVuZ3RoKSkgcmV0dXJuO1xuXG4gICAgdmFyIHJldCA9IF90aGlzLnB1c2goY2h1bmspO1xuICAgIGlmICghcmV0KSB7XG4gICAgICBwYXVzZWQgPSB0cnVlO1xuICAgICAgc3RyZWFtLnBhdXNlKCk7XG4gICAgfVxuICB9KTtcblxuICAvLyBwcm94eSBhbGwgdGhlIG90aGVyIG1ldGhvZHMuXG4gIC8vIGltcG9ydGFudCB3aGVuIHdyYXBwaW5nIGZpbHRlcnMgYW5kIGR1cGxleGVzLlxuICBmb3IgKHZhciBpIGluIHN0cmVhbSkge1xuICAgIGlmICh0aGlzW2ldID09PSB1bmRlZmluZWQgJiYgdHlwZW9mIHN0cmVhbVtpXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhpc1tpXSA9IGZ1bmN0aW9uIChtZXRob2QpIHtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICByZXR1cm4gc3RyZWFtW21ldGhvZF0uYXBwbHkoc3RyZWFtLCBhcmd1bWVudHMpO1xuICAgICAgICB9O1xuICAgICAgfShpKTtcbiAgICB9XG4gIH1cblxuICAvLyBwcm94eSBjZXJ0YWluIGltcG9ydGFudCBldmVudHMuXG4gIGZvciAodmFyIG4gPSAwOyBuIDwga1Byb3h5RXZlbnRzLmxlbmd0aDsgbisrKSB7XG4gICAgc3RyZWFtLm9uKGtQcm94eUV2ZW50c1tuXSwgdGhpcy5lbWl0LmJpbmQodGhpcywga1Byb3h5RXZlbnRzW25dKSk7XG4gIH1cblxuICAvLyB3aGVuIHdlIHRyeSB0byBjb25zdW1lIHNvbWUgbW9yZSBieXRlcywgc2ltcGx5IHVucGF1c2UgdGhlXG4gIC8vIHVuZGVybHlpbmcgc3RyZWFtLlxuICB0aGlzLl9yZWFkID0gZnVuY3Rpb24gKG4pIHtcbiAgICBkZWJ1Zygnd3JhcHBlZCBfcmVhZCcsIG4pO1xuICAgIGlmIChwYXVzZWQpIHtcbiAgICAgIHBhdXNlZCA9IGZhbHNlO1xuICAgICAgc3RyZWFtLnJlc3VtZSgpO1xuICAgIH1cbiAgfTtcblxuICByZXR1cm4gdGhpcztcbn07XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShSZWFkYWJsZS5wcm90b3R5cGUsICdyZWFkYWJsZUhpZ2hXYXRlck1hcmsnLCB7XG4gIC8vIG1ha2luZyBpdCBleHBsaWNpdCB0aGlzIHByb3BlcnR5IGlzIG5vdCBlbnVtZXJhYmxlXG4gIC8vIGJlY2F1c2Ugb3RoZXJ3aXNlIHNvbWUgcHJvdG90eXBlIG1hbmlwdWxhdGlvbiBpblxuICAvLyB1c2VybGFuZCB3aWxsIGZhaWxcbiAgZW51bWVyYWJsZTogZmFsc2UsXG4gIGdldDogZnVuY3Rpb24gKCkge1xuICAgIHJldHVybiB0aGlzLl9yZWFkYWJsZVN0YXRlLmhpZ2hXYXRlck1hcms7XG4gIH1cbn0pO1xuXG4vLyBleHBvc2VkIGZvciB0ZXN0aW5nIHB1cnBvc2VzIG9ubHkuXG5SZWFkYWJsZS5fZnJvbUxpc3QgPSBmcm9tTGlzdDtcblxuLy8gUGx1Y2sgb2ZmIG4gYnl0ZXMgZnJvbSBhbiBhcnJheSBvZiBidWZmZXJzLlxuLy8gTGVuZ3RoIGlzIHRoZSBjb21iaW5lZCBsZW5ndGhzIG9mIGFsbCB0aGUgYnVmZmVycyBpbiB0aGUgbGlzdC5cbi8vIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgaW5saW5hYmxlLCBzbyBwbGVhc2UgdGFrZSBjYXJlIHdoZW4gbWFraW5nXG4vLyBjaGFuZ2VzIHRvIHRoZSBmdW5jdGlvbiBib2R5LlxuZnVuY3Rpb24gZnJvbUxpc3Qobiwgc3RhdGUpIHtcbiAgLy8gbm90aGluZyBidWZmZXJlZFxuICBpZiAoc3RhdGUubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcblxuICB2YXIgcmV0O1xuICBpZiAoc3RhdGUub2JqZWN0TW9kZSkgcmV0ID0gc3RhdGUuYnVmZmVyLnNoaWZ0KCk7ZWxzZSBpZiAoIW4gfHwgbiA+PSBzdGF0ZS5sZW5ndGgpIHtcbiAgICAvLyByZWFkIGl0IGFsbCwgdHJ1bmNhdGUgdGhlIGxpc3RcbiAgICBpZiAoc3RhdGUuZGVjb2RlcikgcmV0ID0gc3RhdGUuYnVmZmVyLmpvaW4oJycpO2Vsc2UgaWYgKHN0YXRlLmJ1ZmZlci5sZW5ndGggPT09IDEpIHJldCA9IHN0YXRlLmJ1ZmZlci5oZWFkLmRhdGE7ZWxzZSByZXQgPSBzdGF0ZS5idWZmZXIuY29uY2F0KHN0YXRlLmxlbmd0aCk7XG4gICAgc3RhdGUuYnVmZmVyLmNsZWFyKCk7XG4gIH0gZWxzZSB7XG4gICAgLy8gcmVhZCBwYXJ0IG9mIGxpc3RcbiAgICByZXQgPSBmcm9tTGlzdFBhcnRpYWwobiwgc3RhdGUuYnVmZmVyLCBzdGF0ZS5kZWNvZGVyKTtcbiAgfVxuXG4gIHJldHVybiByZXQ7XG59XG5cbi8vIEV4dHJhY3RzIG9ubHkgZW5vdWdoIGJ1ZmZlcmVkIGRhdGEgdG8gc2F0aXNmeSB0aGUgYW1vdW50IHJlcXVlc3RlZC5cbi8vIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgaW5saW5hYmxlLCBzbyBwbGVhc2UgdGFrZSBjYXJlIHdoZW4gbWFraW5nXG4vLyBjaGFuZ2VzIHRvIHRoZSBmdW5jdGlvbiBib2R5LlxuZnVuY3Rpb24gZnJvbUxpc3RQYXJ0aWFsKG4sIGxpc3QsIGhhc1N0cmluZ3MpIHtcbiAgdmFyIHJldDtcbiAgaWYgKG4gPCBsaXN0LmhlYWQuZGF0YS5sZW5ndGgpIHtcbiAgICAvLyBzbGljZSBpcyB0aGUgc2FtZSBmb3IgYnVmZmVycyBhbmQgc3RyaW5nc1xuICAgIHJldCA9IGxpc3QuaGVhZC5kYXRhLnNsaWNlKDAsIG4pO1xuICAgIGxpc3QuaGVhZC5kYXRhID0gbGlzdC5oZWFkLmRhdGEuc2xpY2Uobik7XG4gIH0gZWxzZSBpZiAobiA9PT0gbGlzdC5oZWFkLmRhdGEubGVuZ3RoKSB7XG4gICAgLy8gZmlyc3QgY2h1bmsgaXMgYSBwZXJmZWN0IG1hdGNoXG4gICAgcmV0ID0gbGlzdC5zaGlmdCgpO1xuICB9IGVsc2Uge1xuICAgIC8vIHJlc3VsdCBzcGFucyBtb3JlIHRoYW4gb25lIGJ1ZmZlclxuICAgIHJldCA9IGhhc1N0cmluZ3MgPyBjb3B5RnJvbUJ1ZmZlclN0cmluZyhuLCBsaXN0KSA6IGNvcHlGcm9tQnVmZmVyKG4sIGxpc3QpO1xuICB9XG4gIHJldHVybiByZXQ7XG59XG5cbi8vIENvcGllcyBhIHNwZWNpZmllZCBhbW91bnQgb2YgY2hhcmFjdGVycyBmcm9tIHRoZSBsaXN0IG9mIGJ1ZmZlcmVkIGRhdGFcbi8vIGNodW5rcy5cbi8vIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgaW5saW5hYmxlLCBzbyBwbGVhc2UgdGFrZSBjYXJlIHdoZW4gbWFraW5nXG4vLyBjaGFuZ2VzIHRvIHRoZSBmdW5jdGlvbiBib2R5LlxuZnVuY3Rpb24gY29weUZyb21CdWZmZXJTdHJpbmcobiwgbGlzdCkge1xuICB2YXIgcCA9IGxpc3QuaGVhZDtcbiAgdmFyIGMgPSAxO1xuICB2YXIgcmV0ID0gcC5kYXRhO1xuICBuIC09IHJldC5sZW5ndGg7XG4gIHdoaWxlIChwID0gcC5uZXh0KSB7XG4gICAgdmFyIHN0ciA9IHAuZGF0YTtcbiAgICB2YXIgbmIgPSBuID4gc3RyLmxlbmd0aCA/IHN0ci5sZW5ndGggOiBuO1xuICAgIGlmIChuYiA9PT0gc3RyLmxlbmd0aCkgcmV0ICs9IHN0cjtlbHNlIHJldCArPSBzdHIuc2xpY2UoMCwgbik7XG4gICAgbiAtPSBuYjtcbiAgICBpZiAobiA9PT0gMCkge1xuICAgICAgaWYgKG5iID09PSBzdHIubGVuZ3RoKSB7XG4gICAgICAgICsrYztcbiAgICAgICAgaWYgKHAubmV4dCkgbGlzdC5oZWFkID0gcC5uZXh0O2Vsc2UgbGlzdC5oZWFkID0gbGlzdC50YWlsID0gbnVsbDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGxpc3QuaGVhZCA9IHA7XG4gICAgICAgIHAuZGF0YSA9IHN0ci5zbGljZShuYik7XG4gICAgICB9XG4gICAgICBicmVhaztcbiAgICB9XG4gICAgKytjO1xuICB9XG4gIGxpc3QubGVuZ3RoIC09IGM7XG4gIHJldHVybiByZXQ7XG59XG5cbi8vIENvcGllcyBhIHNwZWNpZmllZCBhbW91bnQgb2YgYnl0ZXMgZnJvbSB0aGUgbGlzdCBvZiBidWZmZXJlZCBkYXRhIGNodW5rcy5cbi8vIFRoaXMgZnVuY3Rpb24gaXMgZGVzaWduZWQgdG8gYmUgaW5saW5hYmxlLCBzbyBwbGVhc2UgdGFrZSBjYXJlIHdoZW4gbWFraW5nXG4vLyBjaGFuZ2VzIHRvIHRoZSBmdW5jdGlvbiBib2R5LlxuZnVuY3Rpb24gY29weUZyb21CdWZmZXIobiwgbGlzdCkge1xuICB2YXIgcmV0ID0gQnVmZmVyLmFsbG9jVW5zYWZlKG4pO1xuICB2YXIgcCA9IGxpc3QuaGVhZDtcbiAgdmFyIGMgPSAxO1xuICBwLmRhdGEuY29weShyZXQpO1xuICBuIC09IHAuZGF0YS5sZW5ndGg7XG4gIHdoaWxlIChwID0gcC5uZXh0KSB7XG4gICAgdmFyIGJ1ZiA9IHAuZGF0YTtcbiAgICB2YXIgbmIgPSBuID4gYnVmLmxlbmd0aCA/IGJ1Zi5sZW5ndGggOiBuO1xuICAgIGJ1Zi5jb3B5KHJldCwgcmV0Lmxlbmd0aCAtIG4sIDAsIG5iKTtcbiAgICBuIC09IG5iO1xuICAgIGlmIChuID09PSAwKSB7XG4gICAgICBpZiAobmIgPT09IGJ1Zi5sZW5ndGgpIHtcbiAgICAgICAgKytjO1xuICAgICAgICBpZiAocC5uZXh0KSBsaXN0LmhlYWQgPSBwLm5leHQ7ZWxzZSBsaXN0LmhlYWQgPSBsaXN0LnRhaWwgPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbGlzdC5oZWFkID0gcDtcbiAgICAgICAgcC5kYXRhID0gYnVmLnNsaWNlKG5iKTtcbiAgICAgIH1cbiAgICAgIGJyZWFrO1xuICAgIH1cbiAgICArK2M7XG4gIH1cbiAgbGlzdC5sZW5ndGggLT0gYztcbiAgcmV0dXJuIHJldDtcbn1cblxuZnVuY3Rpb24gZW5kUmVhZGFibGUoc3RyZWFtKSB7XG4gIHZhciBzdGF0ZSA9IHN0cmVhbS5fcmVhZGFibGVTdGF0ZTtcblxuICAvLyBJZiB3ZSBnZXQgaGVyZSBiZWZvcmUgY29uc3VtaW5nIGFsbCB0aGUgYnl0ZXMsIHRoZW4gdGhhdCBpcyBhXG4gIC8vIGJ1ZyBpbiBub2RlLiAgU2hvdWxkIG5ldmVyIGhhcHBlbi5cbiAgaWYgKHN0YXRlLmxlbmd0aCA+IDApIHRocm93IG5ldyBFcnJvcignXCJlbmRSZWFkYWJsZSgpXCIgY2FsbGVkIG9uIG5vbi1lbXB0eSBzdHJlYW0nKTtcblxuICBpZiAoIXN0YXRlLmVuZEVtaXR0ZWQpIHtcbiAgICBzdGF0ZS5lbmRlZCA9IHRydWU7XG4gICAgcG5hLm5leHRUaWNrKGVuZFJlYWRhYmxlTlQsIHN0YXRlLCBzdHJlYW0pO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVuZFJlYWRhYmxlTlQoc3RhdGUsIHN0cmVhbSkge1xuICAvLyBDaGVjayB0aGF0IHdlIGRpZG4ndCBnZXQgb25lIGxhc3QgdW5zaGlmdC5cbiAgaWYgKCFzdGF0ZS5lbmRFbWl0dGVkICYmIHN0YXRlLmxlbmd0aCA9PT0gMCkge1xuICAgIHN0YXRlLmVuZEVtaXR0ZWQgPSB0cnVlO1xuICAgIHN0cmVhbS5yZWFkYWJsZSA9IGZhbHNlO1xuICAgIHN0cmVhbS5lbWl0KCdlbmQnKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpbmRleE9mKHhzLCB4KSB7XG4gIGZvciAodmFyIGkgPSAwLCBsID0geHMubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgaWYgKHhzW2ldID09PSB4KSByZXR1cm4gaTtcbiAgfVxuICByZXR1cm4gLTE7XG59IiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIGEgdHJhbnNmb3JtIHN0cmVhbSBpcyBhIHJlYWRhYmxlL3dyaXRhYmxlIHN0cmVhbSB3aGVyZSB5b3UgZG9cbi8vIHNvbWV0aGluZyB3aXRoIHRoZSBkYXRhLiAgU29tZXRpbWVzIGl0J3MgY2FsbGVkIGEgXCJmaWx0ZXJcIixcbi8vIGJ1dCB0aGF0J3Mgbm90IGEgZ3JlYXQgbmFtZSBmb3IgaXQsIHNpbmNlIHRoYXQgaW1wbGllcyBhIHRoaW5nIHdoZXJlXG4vLyBzb21lIGJpdHMgcGFzcyB0aHJvdWdoLCBhbmQgb3RoZXJzIGFyZSBzaW1wbHkgaWdub3JlZC4gIChUaGF0IHdvdWxkXG4vLyBiZSBhIHZhbGlkIGV4YW1wbGUgb2YgYSB0cmFuc2Zvcm0sIG9mIGNvdXJzZS4pXG4vL1xuLy8gV2hpbGUgdGhlIG91dHB1dCBpcyBjYXVzYWxseSByZWxhdGVkIHRvIHRoZSBpbnB1dCwgaXQncyBub3QgYVxuLy8gbmVjZXNzYXJpbHkgc3ltbWV0cmljIG9yIHN5bmNocm9ub3VzIHRyYW5zZm9ybWF0aW9uLiAgRm9yIGV4YW1wbGUsXG4vLyBhIHpsaWIgc3RyZWFtIG1pZ2h0IHRha2UgbXVsdGlwbGUgcGxhaW4tdGV4dCB3cml0ZXMoKSwgYW5kIHRoZW5cbi8vIGVtaXQgYSBzaW5nbGUgY29tcHJlc3NlZCBjaHVuayBzb21lIHRpbWUgaW4gdGhlIGZ1dHVyZS5cbi8vXG4vLyBIZXJlJ3MgaG93IHRoaXMgd29ya3M6XG4vL1xuLy8gVGhlIFRyYW5zZm9ybSBzdHJlYW0gaGFzIGFsbCB0aGUgYXNwZWN0cyBvZiB0aGUgcmVhZGFibGUgYW5kIHdyaXRhYmxlXG4vLyBzdHJlYW0gY2xhc3Nlcy4gIFdoZW4geW91IHdyaXRlKGNodW5rKSwgdGhhdCBjYWxscyBfd3JpdGUoY2h1bmssY2IpXG4vLyBpbnRlcm5hbGx5LCBhbmQgcmV0dXJucyBmYWxzZSBpZiB0aGVyZSdzIGEgbG90IG9mIHBlbmRpbmcgd3JpdGVzXG4vLyBidWZmZXJlZCB1cC4gIFdoZW4geW91IGNhbGwgcmVhZCgpLCB0aGF0IGNhbGxzIF9yZWFkKG4pIHVudGlsXG4vLyB0aGVyZSdzIGVub3VnaCBwZW5kaW5nIHJlYWRhYmxlIGRhdGEgYnVmZmVyZWQgdXAuXG4vL1xuLy8gSW4gYSB0cmFuc2Zvcm0gc3RyZWFtLCB0aGUgd3JpdHRlbiBkYXRhIGlzIHBsYWNlZCBpbiBhIGJ1ZmZlci4gIFdoZW5cbi8vIF9yZWFkKG4pIGlzIGNhbGxlZCwgaXQgdHJhbnNmb3JtcyB0aGUgcXVldWVkIHVwIGRhdGEsIGNhbGxpbmcgdGhlXG4vLyBidWZmZXJlZCBfd3JpdGUgY2IncyBhcyBpdCBjb25zdW1lcyBjaHVua3MuICBJZiBjb25zdW1pbmcgYSBzaW5nbGVcbi8vIHdyaXR0ZW4gY2h1bmsgd291bGQgcmVzdWx0IGluIG11bHRpcGxlIG91dHB1dCBjaHVua3MsIHRoZW4gdGhlIGZpcnN0XG4vLyBvdXRwdXR0ZWQgYml0IGNhbGxzIHRoZSByZWFkY2IsIGFuZCBzdWJzZXF1ZW50IGNodW5rcyBqdXN0IGdvIGludG9cbi8vIHRoZSByZWFkIGJ1ZmZlciwgYW5kIHdpbGwgY2F1c2UgaXQgdG8gZW1pdCAncmVhZGFibGUnIGlmIG5lY2Vzc2FyeS5cbi8vXG4vLyBUaGlzIHdheSwgYmFjay1wcmVzc3VyZSBpcyBhY3R1YWxseSBkZXRlcm1pbmVkIGJ5IHRoZSByZWFkaW5nIHNpZGUsXG4vLyBzaW5jZSBfcmVhZCBoYXMgdG8gYmUgY2FsbGVkIHRvIHN0YXJ0IHByb2Nlc3NpbmcgYSBuZXcgY2h1bmsuICBIb3dldmVyLFxuLy8gYSBwYXRob2xvZ2ljYWwgaW5mbGF0ZSB0eXBlIG9mIHRyYW5zZm9ybSBjYW4gY2F1c2UgZXhjZXNzaXZlIGJ1ZmZlcmluZ1xuLy8gaGVyZS4gIEZvciBleGFtcGxlLCBpbWFnaW5lIGEgc3RyZWFtIHdoZXJlIGV2ZXJ5IGJ5dGUgb2YgaW5wdXQgaXNcbi8vIGludGVycHJldGVkIGFzIGFuIGludGVnZXIgZnJvbSAwLTI1NSwgYW5kIHRoZW4gcmVzdWx0cyBpbiB0aGF0IG1hbnlcbi8vIGJ5dGVzIG9mIG91dHB1dC4gIFdyaXRpbmcgdGhlIDQgYnl0ZXMge2ZmLGZmLGZmLGZmfSB3b3VsZCByZXN1bHQgaW5cbi8vIDFrYiBvZiBkYXRhIGJlaW5nIG91dHB1dC4gIEluIHRoaXMgY2FzZSwgeW91IGNvdWxkIHdyaXRlIGEgdmVyeSBzbWFsbFxuLy8gYW1vdW50IG9mIGlucHV0LCBhbmQgZW5kIHVwIHdpdGggYSB2ZXJ5IGxhcmdlIGFtb3VudCBvZiBvdXRwdXQuICBJblxuLy8gc3VjaCBhIHBhdGhvbG9naWNhbCBpbmZsYXRpbmcgbWVjaGFuaXNtLCB0aGVyZSdkIGJlIG5vIHdheSB0byB0ZWxsXG4vLyB0aGUgc3lzdGVtIHRvIHN0b3AgZG9pbmcgdGhlIHRyYW5zZm9ybS4gIEEgc2luZ2xlIDRNQiB3cml0ZSBjb3VsZFxuLy8gY2F1c2UgdGhlIHN5c3RlbSB0byBydW4gb3V0IG9mIG1lbW9yeS5cbi8vXG4vLyBIb3dldmVyLCBldmVuIGluIHN1Y2ggYSBwYXRob2xvZ2ljYWwgY2FzZSwgb25seSBhIHNpbmdsZSB3cml0dGVuIGNodW5rXG4vLyB3b3VsZCBiZSBjb25zdW1lZCwgYW5kIHRoZW4gdGhlIHJlc3Qgd291bGQgd2FpdCAodW4tdHJhbnNmb3JtZWQpIHVudGlsXG4vLyB0aGUgcmVzdWx0cyBvZiB0aGUgcHJldmlvdXMgdHJhbnNmb3JtZWQgY2h1bmsgd2VyZSBjb25zdW1lZC5cblxuJ3VzZSBzdHJpY3QnO1xuXG5tb2R1bGUuZXhwb3J0cyA9IFRyYW5zZm9ybTtcblxudmFyIER1cGxleCA9IHJlcXVpcmUoJy4vX3N0cmVhbV9kdXBsZXgnKTtcblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciB1dGlsID0gcmVxdWlyZSgnY29yZS11dGlsLWlzJyk7XG51dGlsLmluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKTtcbi8qPC9yZXBsYWNlbWVudD4qL1xuXG51dGlsLmluaGVyaXRzKFRyYW5zZm9ybSwgRHVwbGV4KTtcblxuZnVuY3Rpb24gYWZ0ZXJUcmFuc2Zvcm0oZXIsIGRhdGEpIHtcbiAgdmFyIHRzID0gdGhpcy5fdHJhbnNmb3JtU3RhdGU7XG4gIHRzLnRyYW5zZm9ybWluZyA9IGZhbHNlO1xuXG4gIHZhciBjYiA9IHRzLndyaXRlY2I7XG5cbiAgaWYgKCFjYikge1xuICAgIHJldHVybiB0aGlzLmVtaXQoJ2Vycm9yJywgbmV3IEVycm9yKCd3cml0ZSBjYWxsYmFjayBjYWxsZWQgbXVsdGlwbGUgdGltZXMnKSk7XG4gIH1cblxuICB0cy53cml0ZWNodW5rID0gbnVsbDtcbiAgdHMud3JpdGVjYiA9IG51bGw7XG5cbiAgaWYgKGRhdGEgIT0gbnVsbCkgLy8gc2luZ2xlIGVxdWFscyBjaGVjayBmb3IgYm90aCBgbnVsbGAgYW5kIGB1bmRlZmluZWRgXG4gICAgdGhpcy5wdXNoKGRhdGEpO1xuXG4gIGNiKGVyKTtcblxuICB2YXIgcnMgPSB0aGlzLl9yZWFkYWJsZVN0YXRlO1xuICBycy5yZWFkaW5nID0gZmFsc2U7XG4gIGlmIChycy5uZWVkUmVhZGFibGUgfHwgcnMubGVuZ3RoIDwgcnMuaGlnaFdhdGVyTWFyaykge1xuICAgIHRoaXMuX3JlYWQocnMuaGlnaFdhdGVyTWFyayk7XG4gIH1cbn1cblxuZnVuY3Rpb24gVHJhbnNmb3JtKG9wdGlvbnMpIHtcbiAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIFRyYW5zZm9ybSkpIHJldHVybiBuZXcgVHJhbnNmb3JtKG9wdGlvbnMpO1xuXG4gIER1cGxleC5jYWxsKHRoaXMsIG9wdGlvbnMpO1xuXG4gIHRoaXMuX3RyYW5zZm9ybVN0YXRlID0ge1xuICAgIGFmdGVyVHJhbnNmb3JtOiBhZnRlclRyYW5zZm9ybS5iaW5kKHRoaXMpLFxuICAgIG5lZWRUcmFuc2Zvcm06IGZhbHNlLFxuICAgIHRyYW5zZm9ybWluZzogZmFsc2UsXG4gICAgd3JpdGVjYjogbnVsbCxcbiAgICB3cml0ZWNodW5rOiBudWxsLFxuICAgIHdyaXRlZW5jb2Rpbmc6IG51bGxcbiAgfTtcblxuICAvLyBzdGFydCBvdXQgYXNraW5nIGZvciBhIHJlYWRhYmxlIGV2ZW50IG9uY2UgZGF0YSBpcyB0cmFuc2Zvcm1lZC5cbiAgdGhpcy5fcmVhZGFibGVTdGF0ZS5uZWVkUmVhZGFibGUgPSB0cnVlO1xuXG4gIC8vIHdlIGhhdmUgaW1wbGVtZW50ZWQgdGhlIF9yZWFkIG1ldGhvZCwgYW5kIGRvbmUgdGhlIG90aGVyIHRoaW5nc1xuICAvLyB0aGF0IFJlYWRhYmxlIHdhbnRzIGJlZm9yZSB0aGUgZmlyc3QgX3JlYWQgY2FsbCwgc28gdW5zZXQgdGhlXG4gIC8vIHN5bmMgZ3VhcmQgZmxhZy5cbiAgdGhpcy5fcmVhZGFibGVTdGF0ZS5zeW5jID0gZmFsc2U7XG5cbiAgaWYgKG9wdGlvbnMpIHtcbiAgICBpZiAodHlwZW9mIG9wdGlvbnMudHJhbnNmb3JtID09PSAnZnVuY3Rpb24nKSB0aGlzLl90cmFuc2Zvcm0gPSBvcHRpb25zLnRyYW5zZm9ybTtcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5mbHVzaCA9PT0gJ2Z1bmN0aW9uJykgdGhpcy5fZmx1c2ggPSBvcHRpb25zLmZsdXNoO1xuICB9XG5cbiAgLy8gV2hlbiB0aGUgd3JpdGFibGUgc2lkZSBmaW5pc2hlcywgdGhlbiBmbHVzaCBvdXQgYW55dGhpbmcgcmVtYWluaW5nLlxuICB0aGlzLm9uKCdwcmVmaW5pc2gnLCBwcmVmaW5pc2gpO1xufVxuXG5mdW5jdGlvbiBwcmVmaW5pc2goKSB7XG4gIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgaWYgKHR5cGVvZiB0aGlzLl9mbHVzaCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHRoaXMuX2ZsdXNoKGZ1bmN0aW9uIChlciwgZGF0YSkge1xuICAgICAgZG9uZShfdGhpcywgZXIsIGRhdGEpO1xuICAgIH0pO1xuICB9IGVsc2Uge1xuICAgIGRvbmUodGhpcywgbnVsbCwgbnVsbCk7XG4gIH1cbn1cblxuVHJhbnNmb3JtLnByb3RvdHlwZS5wdXNoID0gZnVuY3Rpb24gKGNodW5rLCBlbmNvZGluZykge1xuICB0aGlzLl90cmFuc2Zvcm1TdGF0ZS5uZWVkVHJhbnNmb3JtID0gZmFsc2U7XG4gIHJldHVybiBEdXBsZXgucHJvdG90eXBlLnB1c2guY2FsbCh0aGlzLCBjaHVuaywgZW5jb2RpbmcpO1xufTtcblxuLy8gVGhpcyBpcyB0aGUgcGFydCB3aGVyZSB5b3UgZG8gc3R1ZmYhXG4vLyBvdmVycmlkZSB0aGlzIGZ1bmN0aW9uIGluIGltcGxlbWVudGF0aW9uIGNsYXNzZXMuXG4vLyAnY2h1bmsnIGlzIGFuIGlucHV0IGNodW5rLlxuLy9cbi8vIENhbGwgYHB1c2gobmV3Q2h1bmspYCB0byBwYXNzIGFsb25nIHRyYW5zZm9ybWVkIG91dHB1dFxuLy8gdG8gdGhlIHJlYWRhYmxlIHNpZGUuICBZb3UgbWF5IGNhbGwgJ3B1c2gnIHplcm8gb3IgbW9yZSB0aW1lcy5cbi8vXG4vLyBDYWxsIGBjYihlcnIpYCB3aGVuIHlvdSBhcmUgZG9uZSB3aXRoIHRoaXMgY2h1bmsuICBJZiB5b3UgcGFzc1xuLy8gYW4gZXJyb3IsIHRoZW4gdGhhdCdsbCBwdXQgdGhlIGh1cnQgb24gdGhlIHdob2xlIG9wZXJhdGlvbi4gIElmIHlvdVxuLy8gbmV2ZXIgY2FsbCBjYigpLCB0aGVuIHlvdSdsbCBuZXZlciBnZXQgYW5vdGhlciBjaHVuay5cblRyYW5zZm9ybS5wcm90b3R5cGUuX3RyYW5zZm9ybSA9IGZ1bmN0aW9uIChjaHVuaywgZW5jb2RpbmcsIGNiKSB7XG4gIHRocm93IG5ldyBFcnJvcignX3RyYW5zZm9ybSgpIGlzIG5vdCBpbXBsZW1lbnRlZCcpO1xufTtcblxuVHJhbnNmb3JtLnByb3RvdHlwZS5fd3JpdGUgPSBmdW5jdGlvbiAoY2h1bmssIGVuY29kaW5nLCBjYikge1xuICB2YXIgdHMgPSB0aGlzLl90cmFuc2Zvcm1TdGF0ZTtcbiAgdHMud3JpdGVjYiA9IGNiO1xuICB0cy53cml0ZWNodW5rID0gY2h1bms7XG4gIHRzLndyaXRlZW5jb2RpbmcgPSBlbmNvZGluZztcbiAgaWYgKCF0cy50cmFuc2Zvcm1pbmcpIHtcbiAgICB2YXIgcnMgPSB0aGlzLl9yZWFkYWJsZVN0YXRlO1xuICAgIGlmICh0cy5uZWVkVHJhbnNmb3JtIHx8IHJzLm5lZWRSZWFkYWJsZSB8fCBycy5sZW5ndGggPCBycy5oaWdoV2F0ZXJNYXJrKSB0aGlzLl9yZWFkKHJzLmhpZ2hXYXRlck1hcmspO1xuICB9XG59O1xuXG4vLyBEb2Vzbid0IG1hdHRlciB3aGF0IHRoZSBhcmdzIGFyZSBoZXJlLlxuLy8gX3RyYW5zZm9ybSBkb2VzIGFsbCB0aGUgd29yay5cbi8vIFRoYXQgd2UgZ290IGhlcmUgbWVhbnMgdGhhdCB0aGUgcmVhZGFibGUgc2lkZSB3YW50cyBtb3JlIGRhdGEuXG5UcmFuc2Zvcm0ucHJvdG90eXBlLl9yZWFkID0gZnVuY3Rpb24gKG4pIHtcbiAgdmFyIHRzID0gdGhpcy5fdHJhbnNmb3JtU3RhdGU7XG5cbiAgaWYgKHRzLndyaXRlY2h1bmsgIT09IG51bGwgJiYgdHMud3JpdGVjYiAmJiAhdHMudHJhbnNmb3JtaW5nKSB7XG4gICAgdHMudHJhbnNmb3JtaW5nID0gdHJ1ZTtcbiAgICB0aGlzLl90cmFuc2Zvcm0odHMud3JpdGVjaHVuaywgdHMud3JpdGVlbmNvZGluZywgdHMuYWZ0ZXJUcmFuc2Zvcm0pO1xuICB9IGVsc2Uge1xuICAgIC8vIG1hcmsgdGhhdCB3ZSBuZWVkIGEgdHJhbnNmb3JtLCBzbyB0aGF0IGFueSBkYXRhIHRoYXQgY29tZXMgaW5cbiAgICAvLyB3aWxsIGdldCBwcm9jZXNzZWQsIG5vdyB0aGF0IHdlJ3ZlIGFza2VkIGZvciBpdC5cbiAgICB0cy5uZWVkVHJhbnNmb3JtID0gdHJ1ZTtcbiAgfVxufTtcblxuVHJhbnNmb3JtLnByb3RvdHlwZS5fZGVzdHJveSA9IGZ1bmN0aW9uIChlcnIsIGNiKSB7XG4gIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gIER1cGxleC5wcm90b3R5cGUuX2Rlc3Ryb3kuY2FsbCh0aGlzLCBlcnIsIGZ1bmN0aW9uIChlcnIyKSB7XG4gICAgY2IoZXJyMik7XG4gICAgX3RoaXMyLmVtaXQoJ2Nsb3NlJyk7XG4gIH0pO1xufTtcblxuZnVuY3Rpb24gZG9uZShzdHJlYW0sIGVyLCBkYXRhKSB7XG4gIGlmIChlcikgcmV0dXJuIHN0cmVhbS5lbWl0KCdlcnJvcicsIGVyKTtcblxuICBpZiAoZGF0YSAhPSBudWxsKSAvLyBzaW5nbGUgZXF1YWxzIGNoZWNrIGZvciBib3RoIGBudWxsYCBhbmQgYHVuZGVmaW5lZGBcbiAgICBzdHJlYW0ucHVzaChkYXRhKTtcblxuICAvLyBpZiB0aGVyZSdzIG5vdGhpbmcgaW4gdGhlIHdyaXRlIGJ1ZmZlciwgdGhlbiB0aGF0IG1lYW5zXG4gIC8vIHRoYXQgbm90aGluZyBtb3JlIHdpbGwgZXZlciBiZSBwcm92aWRlZFxuICBpZiAoc3RyZWFtLl93cml0YWJsZVN0YXRlLmxlbmd0aCkgdGhyb3cgbmV3IEVycm9yKCdDYWxsaW5nIHRyYW5zZm9ybSBkb25lIHdoZW4gd3MubGVuZ3RoICE9IDAnKTtcblxuICBpZiAoc3RyZWFtLl90cmFuc2Zvcm1TdGF0ZS50cmFuc2Zvcm1pbmcpIHRocm93IG5ldyBFcnJvcignQ2FsbGluZyB0cmFuc2Zvcm0gZG9uZSB3aGVuIHN0aWxsIHRyYW5zZm9ybWluZycpO1xuXG4gIHJldHVybiBzdHJlYW0ucHVzaChudWxsKTtcbn0iLCIvLyBDb3B5cmlnaHQgSm95ZW50LCBJbmMuIGFuZCBvdGhlciBOb2RlIGNvbnRyaWJ1dG9ycy5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYVxuLy8gY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZVxuLy8gXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nXG4vLyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsXG4vLyBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbCBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0XG4vLyBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGVcbi8vIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkXG4vLyBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTXG4vLyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GXG4vLyBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOXG4vLyBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSxcbi8vIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUlxuLy8gT1RIRVJXSVNFLCBBUklTSU5HIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRVxuLy8gVVNFIE9SIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cblxuLy8gQSBiaXQgc2ltcGxlciB0aGFuIHJlYWRhYmxlIHN0cmVhbXMuXG4vLyBJbXBsZW1lbnQgYW4gYXN5bmMgLl93cml0ZShjaHVuaywgZW5jb2RpbmcsIGNiKSwgYW5kIGl0J2xsIGhhbmRsZSBhbGxcbi8vIHRoZSBkcmFpbiBldmVudCBlbWlzc2lvbiBhbmQgYnVmZmVyaW5nLlxuXG4ndXNlIHN0cmljdCc7XG5cbi8qPHJlcGxhY2VtZW50PiovXG5cbnZhciBwbmEgPSByZXF1aXJlKCdwcm9jZXNzLW5leHRpY2stYXJncycpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbm1vZHVsZS5leHBvcnRzID0gV3JpdGFibGU7XG5cbi8qIDxyZXBsYWNlbWVudD4gKi9cbmZ1bmN0aW9uIFdyaXRlUmVxKGNodW5rLCBlbmNvZGluZywgY2IpIHtcbiAgdGhpcy5jaHVuayA9IGNodW5rO1xuICB0aGlzLmVuY29kaW5nID0gZW5jb2Rpbmc7XG4gIHRoaXMuY2FsbGJhY2sgPSBjYjtcbiAgdGhpcy5uZXh0ID0gbnVsbDtcbn1cblxuLy8gSXQgc2VlbXMgYSBsaW5rZWQgbGlzdCBidXQgaXQgaXMgbm90XG4vLyB0aGVyZSB3aWxsIGJlIG9ubHkgMiBvZiB0aGVzZSBmb3IgZWFjaCBzdHJlYW1cbmZ1bmN0aW9uIENvcmtlZFJlcXVlc3Qoc3RhdGUpIHtcbiAgdmFyIF90aGlzID0gdGhpcztcblxuICB0aGlzLm5leHQgPSBudWxsO1xuICB0aGlzLmVudHJ5ID0gbnVsbDtcbiAgdGhpcy5maW5pc2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgb25Db3JrZWRGaW5pc2goX3RoaXMsIHN0YXRlKTtcbiAgfTtcbn1cbi8qIDwvcmVwbGFjZW1lbnQ+ICovXG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgYXN5bmNXcml0ZSA9ICFwcm9jZXNzLmJyb3dzZXIgJiYgWyd2MC4xMCcsICd2MC45LiddLmluZGV4T2YocHJvY2Vzcy52ZXJzaW9uLnNsaWNlKDAsIDUpKSA+IC0xID8gc2V0SW1tZWRpYXRlIDogcG5hLm5leHRUaWNrO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgRHVwbGV4O1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbldyaXRhYmxlLldyaXRhYmxlU3RhdGUgPSBXcml0YWJsZVN0YXRlO1xuXG4vKjxyZXBsYWNlbWVudD4qL1xudmFyIHV0aWwgPSByZXF1aXJlKCdjb3JlLXV0aWwtaXMnKTtcbnV0aWwuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbi8qPHJlcGxhY2VtZW50PiovXG52YXIgaW50ZXJuYWxVdGlsID0ge1xuICBkZXByZWNhdGU6IHJlcXVpcmUoJ3V0aWwtZGVwcmVjYXRlJylcbn07XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cbnZhciBTdHJlYW0gPSByZXF1aXJlKCcuL2ludGVybmFsL3N0cmVhbXMvc3RyZWFtJyk7XG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxuLyo8cmVwbGFjZW1lbnQ+Ki9cblxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyO1xudmFyIE91clVpbnQ4QXJyYXkgPSBnbG9iYWwuVWludDhBcnJheSB8fCBmdW5jdGlvbiAoKSB7fTtcbmZ1bmN0aW9uIF91aW50OEFycmF5VG9CdWZmZXIoY2h1bmspIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKGNodW5rKTtcbn1cbmZ1bmN0aW9uIF9pc1VpbnQ4QXJyYXkob2JqKSB7XG4gIHJldHVybiBCdWZmZXIuaXNCdWZmZXIob2JqKSB8fCBvYmogaW5zdGFuY2VvZiBPdXJVaW50OEFycmF5O1xufVxuXG4vKjwvcmVwbGFjZW1lbnQ+Ki9cblxudmFyIGRlc3Ryb3lJbXBsID0gcmVxdWlyZSgnLi9pbnRlcm5hbC9zdHJlYW1zL2Rlc3Ryb3knKTtcblxudXRpbC5pbmhlcml0cyhXcml0YWJsZSwgU3RyZWFtKTtcblxuZnVuY3Rpb24gbm9wKCkge31cblxuZnVuY3Rpb24gV3JpdGFibGVTdGF0ZShvcHRpb25zLCBzdHJlYW0pIHtcbiAgRHVwbGV4ID0gRHVwbGV4IHx8IHJlcXVpcmUoJy4vX3N0cmVhbV9kdXBsZXgnKTtcblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICAvLyBEdXBsZXggc3RyZWFtcyBhcmUgYm90aCByZWFkYWJsZSBhbmQgd3JpdGFibGUsIGJ1dCBzaGFyZVxuICAvLyB0aGUgc2FtZSBvcHRpb25zIG9iamVjdC5cbiAgLy8gSG93ZXZlciwgc29tZSBjYXNlcyByZXF1aXJlIHNldHRpbmcgb3B0aW9ucyB0byBkaWZmZXJlbnRcbiAgLy8gdmFsdWVzIGZvciB0aGUgcmVhZGFibGUgYW5kIHRoZSB3cml0YWJsZSBzaWRlcyBvZiB0aGUgZHVwbGV4IHN0cmVhbS5cbiAgLy8gVGhlc2Ugb3B0aW9ucyBjYW4gYmUgcHJvdmlkZWQgc2VwYXJhdGVseSBhcyByZWFkYWJsZVhYWCBhbmQgd3JpdGFibGVYWFguXG4gIHZhciBpc0R1cGxleCA9IHN0cmVhbSBpbnN0YW5jZW9mIER1cGxleDtcblxuICAvLyBvYmplY3Qgc3RyZWFtIGZsYWcgdG8gaW5kaWNhdGUgd2hldGhlciBvciBub3QgdGhpcyBzdHJlYW1cbiAgLy8gY29udGFpbnMgYnVmZmVycyBvciBvYmplY3RzLlxuICB0aGlzLm9iamVjdE1vZGUgPSAhIW9wdGlvbnMub2JqZWN0TW9kZTtcblxuICBpZiAoaXNEdXBsZXgpIHRoaXMub2JqZWN0TW9kZSA9IHRoaXMub2JqZWN0TW9kZSB8fCAhIW9wdGlvbnMud3JpdGFibGVPYmplY3RNb2RlO1xuXG4gIC8vIHRoZSBwb2ludCBhdCB3aGljaCB3cml0ZSgpIHN0YXJ0cyByZXR1cm5pbmcgZmFsc2VcbiAgLy8gTm90ZTogMCBpcyBhIHZhbGlkIHZhbHVlLCBtZWFucyB0aGF0IHdlIGFsd2F5cyByZXR1cm4gZmFsc2UgaWZcbiAgLy8gdGhlIGVudGlyZSBidWZmZXIgaXMgbm90IGZsdXNoZWQgaW1tZWRpYXRlbHkgb24gd3JpdGUoKVxuICB2YXIgaHdtID0gb3B0aW9ucy5oaWdoV2F0ZXJNYXJrO1xuICB2YXIgd3JpdGFibGVId20gPSBvcHRpb25zLndyaXRhYmxlSGlnaFdhdGVyTWFyaztcbiAgdmFyIGRlZmF1bHRId20gPSB0aGlzLm9iamVjdE1vZGUgPyAxNiA6IDE2ICogMTAyNDtcblxuICBpZiAoaHdtIHx8IGh3bSA9PT0gMCkgdGhpcy5oaWdoV2F0ZXJNYXJrID0gaHdtO2Vsc2UgaWYgKGlzRHVwbGV4ICYmICh3cml0YWJsZUh3bSB8fCB3cml0YWJsZUh3bSA9PT0gMCkpIHRoaXMuaGlnaFdhdGVyTWFyayA9IHdyaXRhYmxlSHdtO2Vsc2UgdGhpcy5oaWdoV2F0ZXJNYXJrID0gZGVmYXVsdEh3bTtcblxuICAvLyBjYXN0IHRvIGludHMuXG4gIHRoaXMuaGlnaFdhdGVyTWFyayA9IE1hdGguZmxvb3IodGhpcy5oaWdoV2F0ZXJNYXJrKTtcblxuICAvLyBpZiBfZmluYWwgaGFzIGJlZW4gY2FsbGVkXG4gIHRoaXMuZmluYWxDYWxsZWQgPSBmYWxzZTtcblxuICAvLyBkcmFpbiBldmVudCBmbGFnLlxuICB0aGlzLm5lZWREcmFpbiA9IGZhbHNlO1xuICAvLyBhdCB0aGUgc3RhcnQgb2YgY2FsbGluZyBlbmQoKVxuICB0aGlzLmVuZGluZyA9IGZhbHNlO1xuICAvLyB3aGVuIGVuZCgpIGhhcyBiZWVuIGNhbGxlZCwgYW5kIHJldHVybmVkXG4gIHRoaXMuZW5kZWQgPSBmYWxzZTtcbiAgLy8gd2hlbiAnZmluaXNoJyBpcyBlbWl0dGVkXG4gIHRoaXMuZmluaXNoZWQgPSBmYWxzZTtcblxuICAvLyBoYXMgaXQgYmVlbiBkZXN0cm95ZWRcbiAgdGhpcy5kZXN0cm95ZWQgPSBmYWxzZTtcblxuICAvLyBzaG91bGQgd2UgZGVjb2RlIHN0cmluZ3MgaW50byBidWZmZXJzIGJlZm9yZSBwYXNzaW5nIHRvIF93cml0ZT9cbiAgLy8gdGhpcyBpcyBoZXJlIHNvIHRoYXQgc29tZSBub2RlLWNvcmUgc3RyZWFtcyBjYW4gb3B0aW1pemUgc3RyaW5nXG4gIC8vIGhhbmRsaW5nIGF0IGEgbG93ZXIgbGV2ZWwuXG4gIHZhciBub0RlY29kZSA9IG9wdGlvbnMuZGVjb2RlU3RyaW5ncyA9PT0gZmFsc2U7XG4gIHRoaXMuZGVjb2RlU3RyaW5ncyA9ICFub0RlY29kZTtcblxuICAvLyBDcnlwdG8gaXMga2luZCBvZiBvbGQgYW5kIGNydXN0eS4gIEhpc3RvcmljYWxseSwgaXRzIGRlZmF1bHQgc3RyaW5nXG4gIC8vIGVuY29kaW5nIGlzICdiaW5hcnknIHNvIHdlIGhhdmUgdG8gbWFrZSB0aGlzIGNvbmZpZ3VyYWJsZS5cbiAgLy8gRXZlcnl0aGluZyBlbHNlIGluIHRoZSB1bml2ZXJzZSB1c2VzICd1dGY4JywgdGhvdWdoLlxuICB0aGlzLmRlZmF1bHRFbmNvZGluZyA9IG9wdGlvbnMuZGVmYXVsdEVuY29kaW5nIHx8ICd1dGY4JztcblxuICAvLyBub3QgYW4gYWN0dWFsIGJ1ZmZlciB3ZSBrZWVwIHRyYWNrIG9mLCBidXQgYSBtZWFzdXJlbWVudFxuICAvLyBvZiBob3cgbXVjaCB3ZSdyZSB3YWl0aW5nIHRvIGdldCBwdXNoZWQgdG8gc29tZSB1bmRlcmx5aW5nXG4gIC8vIHNvY2tldCBvciBmaWxlLlxuICB0aGlzLmxlbmd0aCA9IDA7XG5cbiAgLy8gYSBmbGFnIHRvIHNlZSB3aGVuIHdlJ3JlIGluIHRoZSBtaWRkbGUgb2YgYSB3cml0ZS5cbiAgdGhpcy53cml0aW5nID0gZmFsc2U7XG5cbiAgLy8gd2hlbiB0cnVlIGFsbCB3cml0ZXMgd2lsbCBiZSBidWZmZXJlZCB1bnRpbCAudW5jb3JrKCkgY2FsbFxuICB0aGlzLmNvcmtlZCA9IDA7XG5cbiAgLy8gYSBmbGFnIHRvIGJlIGFibGUgdG8gdGVsbCBpZiB0aGUgb253cml0ZSBjYiBpcyBjYWxsZWQgaW1tZWRpYXRlbHksXG4gIC8vIG9yIG9uIGEgbGF0ZXIgdGljay4gIFdlIHNldCB0aGlzIHRvIHRydWUgYXQgZmlyc3QsIGJlY2F1c2UgYW55XG4gIC8vIGFjdGlvbnMgdGhhdCBzaG91bGRuJ3QgaGFwcGVuIHVudGlsIFwibGF0ZXJcIiBzaG91bGQgZ2VuZXJhbGx5IGFsc29cbiAgLy8gbm90IGhhcHBlbiBiZWZvcmUgdGhlIGZpcnN0IHdyaXRlIGNhbGwuXG4gIHRoaXMuc3luYyA9IHRydWU7XG5cbiAgLy8gYSBmbGFnIHRvIGtub3cgaWYgd2UncmUgcHJvY2Vzc2luZyBwcmV2aW91c2x5IGJ1ZmZlcmVkIGl0ZW1zLCB3aGljaFxuICAvLyBtYXkgY2FsbCB0aGUgX3dyaXRlKCkgY2FsbGJhY2sgaW4gdGhlIHNhbWUgdGljaywgc28gdGhhdCB3ZSBkb24ndFxuICAvLyBlbmQgdXAgaW4gYW4gb3ZlcmxhcHBlZCBvbndyaXRlIHNpdHVhdGlvbi5cbiAgdGhpcy5idWZmZXJQcm9jZXNzaW5nID0gZmFsc2U7XG5cbiAgLy8gdGhlIGNhbGxiYWNrIHRoYXQncyBwYXNzZWQgdG8gX3dyaXRlKGNodW5rLGNiKVxuICB0aGlzLm9ud3JpdGUgPSBmdW5jdGlvbiAoZXIpIHtcbiAgICBvbndyaXRlKHN0cmVhbSwgZXIpO1xuICB9O1xuXG4gIC8vIHRoZSBjYWxsYmFjayB0aGF0IHRoZSB1c2VyIHN1cHBsaWVzIHRvIHdyaXRlKGNodW5rLGVuY29kaW5nLGNiKVxuICB0aGlzLndyaXRlY2IgPSBudWxsO1xuXG4gIC8vIHRoZSBhbW91bnQgdGhhdCBpcyBiZWluZyB3cml0dGVuIHdoZW4gX3dyaXRlIGlzIGNhbGxlZC5cbiAgdGhpcy53cml0ZWxlbiA9IDA7XG5cbiAgdGhpcy5idWZmZXJlZFJlcXVlc3QgPSBudWxsO1xuICB0aGlzLmxhc3RCdWZmZXJlZFJlcXVlc3QgPSBudWxsO1xuXG4gIC8vIG51bWJlciBvZiBwZW5kaW5nIHVzZXItc3VwcGxpZWQgd3JpdGUgY2FsbGJhY2tzXG4gIC8vIHRoaXMgbXVzdCBiZSAwIGJlZm9yZSAnZmluaXNoJyBjYW4gYmUgZW1pdHRlZFxuICB0aGlzLnBlbmRpbmdjYiA9IDA7XG5cbiAgLy8gZW1pdCBwcmVmaW5pc2ggaWYgdGhlIG9ubHkgdGhpbmcgd2UncmUgd2FpdGluZyBmb3IgaXMgX3dyaXRlIGNic1xuICAvLyBUaGlzIGlzIHJlbGV2YW50IGZvciBzeW5jaHJvbm91cyBUcmFuc2Zvcm0gc3RyZWFtc1xuICB0aGlzLnByZWZpbmlzaGVkID0gZmFsc2U7XG5cbiAgLy8gVHJ1ZSBpZiB0aGUgZXJyb3Igd2FzIGFscmVhZHkgZW1pdHRlZCBhbmQgc2hvdWxkIG5vdCBiZSB0aHJvd24gYWdhaW5cbiAgdGhpcy5lcnJvckVtaXR0ZWQgPSBmYWxzZTtcblxuICAvLyBjb3VudCBidWZmZXJlZCByZXF1ZXN0c1xuICB0aGlzLmJ1ZmZlcmVkUmVxdWVzdENvdW50ID0gMDtcblxuICAvLyBhbGxvY2F0ZSB0aGUgZmlyc3QgQ29ya2VkUmVxdWVzdCwgdGhlcmUgaXMgYWx3YXlzXG4gIC8vIG9uZSBhbGxvY2F0ZWQgYW5kIGZyZWUgdG8gdXNlLCBhbmQgd2UgbWFpbnRhaW4gYXQgbW9zdCB0d29cbiAgdGhpcy5jb3JrZWRSZXF1ZXN0c0ZyZWUgPSBuZXcgQ29ya2VkUmVxdWVzdCh0aGlzKTtcbn1cblxuV3JpdGFibGVTdGF0ZS5wcm90b3R5cGUuZ2V0QnVmZmVyID0gZnVuY3Rpb24gZ2V0QnVmZmVyKCkge1xuICB2YXIgY3VycmVudCA9IHRoaXMuYnVmZmVyZWRSZXF1ZXN0O1xuICB2YXIgb3V0ID0gW107XG4gIHdoaWxlIChjdXJyZW50KSB7XG4gICAgb3V0LnB1c2goY3VycmVudCk7XG4gICAgY3VycmVudCA9IGN1cnJlbnQubmV4dDtcbiAgfVxuICByZXR1cm4gb3V0O1xufTtcblxuKGZ1bmN0aW9uICgpIHtcbiAgdHJ5IHtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoV3JpdGFibGVTdGF0ZS5wcm90b3R5cGUsICdidWZmZXInLCB7XG4gICAgICBnZXQ6IGludGVybmFsVXRpbC5kZXByZWNhdGUoZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRCdWZmZXIoKTtcbiAgICAgIH0sICdfd3JpdGFibGVTdGF0ZS5idWZmZXIgaXMgZGVwcmVjYXRlZC4gVXNlIF93cml0YWJsZVN0YXRlLmdldEJ1ZmZlciAnICsgJ2luc3RlYWQuJywgJ0RFUDAwMDMnKVxuICAgIH0pO1xuICB9IGNhdGNoIChfKSB7fVxufSkoKTtcblxuLy8gVGVzdCBfd3JpdGFibGVTdGF0ZSBmb3IgaW5oZXJpdGFuY2UgdG8gYWNjb3VudCBmb3IgRHVwbGV4IHN0cmVhbXMsXG4vLyB3aG9zZSBwcm90b3R5cGUgY2hhaW4gb25seSBwb2ludHMgdG8gUmVhZGFibGUuXG52YXIgcmVhbEhhc0luc3RhbmNlO1xuaWYgKHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicgJiYgU3ltYm9sLmhhc0luc3RhbmNlICYmIHR5cGVvZiBGdW5jdGlvbi5wcm90b3R5cGVbU3ltYm9sLmhhc0luc3RhbmNlXSA9PT0gJ2Z1bmN0aW9uJykge1xuICByZWFsSGFzSW5zdGFuY2UgPSBGdW5jdGlvbi5wcm90b3R5cGVbU3ltYm9sLmhhc0luc3RhbmNlXTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFdyaXRhYmxlLCBTeW1ib2wuaGFzSW5zdGFuY2UsIHtcbiAgICB2YWx1ZTogZnVuY3Rpb24gKG9iamVjdCkge1xuICAgICAgaWYgKHJlYWxIYXNJbnN0YW5jZS5jYWxsKHRoaXMsIG9iamVjdCkpIHJldHVybiB0cnVlO1xuICAgICAgaWYgKHRoaXMgIT09IFdyaXRhYmxlKSByZXR1cm4gZmFsc2U7XG5cbiAgICAgIHJldHVybiBvYmplY3QgJiYgb2JqZWN0Ll93cml0YWJsZVN0YXRlIGluc3RhbmNlb2YgV3JpdGFibGVTdGF0ZTtcbiAgICB9XG4gIH0pO1xufSBlbHNlIHtcbiAgcmVhbEhhc0luc3RhbmNlID0gZnVuY3Rpb24gKG9iamVjdCkge1xuICAgIHJldHVybiBvYmplY3QgaW5zdGFuY2VvZiB0aGlzO1xuICB9O1xufVxuXG5mdW5jdGlvbiBXcml0YWJsZShvcHRpb25zKSB7XG4gIER1cGxleCA9IER1cGxleCB8fCByZXF1aXJlKCcuL19zdHJlYW1fZHVwbGV4Jyk7XG5cbiAgLy8gV3JpdGFibGUgY3RvciBpcyBhcHBsaWVkIHRvIER1cGxleGVzLCB0b28uXG4gIC8vIGByZWFsSGFzSW5zdGFuY2VgIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHVzaW5nIHBsYWluIGBpbnN0YW5jZW9mYFxuICAvLyB3b3VsZCByZXR1cm4gZmFsc2UsIGFzIG5vIGBfd3JpdGFibGVTdGF0ZWAgcHJvcGVydHkgaXMgYXR0YWNoZWQuXG5cbiAgLy8gVHJ5aW5nIHRvIHVzZSB0aGUgY3VzdG9tIGBpbnN0YW5jZW9mYCBmb3IgV3JpdGFibGUgaGVyZSB3aWxsIGFsc28gYnJlYWsgdGhlXG4gIC8vIE5vZGUuanMgTGF6eVRyYW5zZm9ybSBpbXBsZW1lbnRhdGlvbiwgd2hpY2ggaGFzIGEgbm9uLXRyaXZpYWwgZ2V0dGVyIGZvclxuICAvLyBgX3dyaXRhYmxlU3RhdGVgIHRoYXQgd291bGQgbGVhZCB0byBpbmZpbml0ZSByZWN1cnNpb24uXG4gIGlmICghcmVhbEhhc0luc3RhbmNlLmNhbGwoV3JpdGFibGUsIHRoaXMpICYmICEodGhpcyBpbnN0YW5jZW9mIER1cGxleCkpIHtcbiAgICByZXR1cm4gbmV3IFdyaXRhYmxlKG9wdGlvbnMpO1xuICB9XG5cbiAgdGhpcy5fd3JpdGFibGVTdGF0ZSA9IG5ldyBXcml0YWJsZVN0YXRlKG9wdGlvbnMsIHRoaXMpO1xuXG4gIC8vIGxlZ2FjeS5cbiAgdGhpcy53cml0YWJsZSA9IHRydWU7XG5cbiAgaWYgKG9wdGlvbnMpIHtcbiAgICBpZiAodHlwZW9mIG9wdGlvbnMud3JpdGUgPT09ICdmdW5jdGlvbicpIHRoaXMuX3dyaXRlID0gb3B0aW9ucy53cml0ZTtcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy53cml0ZXYgPT09ICdmdW5jdGlvbicpIHRoaXMuX3dyaXRldiA9IG9wdGlvbnMud3JpdGV2O1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmRlc3Ryb3kgPT09ICdmdW5jdGlvbicpIHRoaXMuX2Rlc3Ryb3kgPSBvcHRpb25zLmRlc3Ryb3k7XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMuZmluYWwgPT09ICdmdW5jdGlvbicpIHRoaXMuX2ZpbmFsID0gb3B0aW9ucy5maW5hbDtcbiAgfVxuXG4gIFN0cmVhbS5jYWxsKHRoaXMpO1xufVxuXG4vLyBPdGhlcndpc2UgcGVvcGxlIGNhbiBwaXBlIFdyaXRhYmxlIHN0cmVhbXMsIHdoaWNoIGlzIGp1c3Qgd3JvbmcuXG5Xcml0YWJsZS5wcm90b3R5cGUucGlwZSA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5lbWl0KCdlcnJvcicsIG5ldyBFcnJvcignQ2Fubm90IHBpcGUsIG5vdCByZWFkYWJsZScpKTtcbn07XG5cbmZ1bmN0aW9uIHdyaXRlQWZ0ZXJFbmQoc3RyZWFtLCBjYikge1xuICB2YXIgZXIgPSBuZXcgRXJyb3IoJ3dyaXRlIGFmdGVyIGVuZCcpO1xuICAvLyBUT0RPOiBkZWZlciBlcnJvciBldmVudHMgY29uc2lzdGVudGx5IGV2ZXJ5d2hlcmUsIG5vdCBqdXN0IHRoZSBjYlxuICBzdHJlYW0uZW1pdCgnZXJyb3InLCBlcik7XG4gIHBuYS5uZXh0VGljayhjYiwgZXIpO1xufVxuXG4vLyBDaGVja3MgdGhhdCBhIHVzZXItc3VwcGxpZWQgY2h1bmsgaXMgdmFsaWQsIGVzcGVjaWFsbHkgZm9yIHRoZSBwYXJ0aWN1bGFyXG4vLyBtb2RlIHRoZSBzdHJlYW0gaXMgaW4uIEN1cnJlbnRseSB0aGlzIG1lYW5zIHRoYXQgYG51bGxgIGlzIG5ldmVyIGFjY2VwdGVkXG4vLyBhbmQgdW5kZWZpbmVkL25vbi1zdHJpbmcgdmFsdWVzIGFyZSBvbmx5IGFsbG93ZWQgaW4gb2JqZWN0IG1vZGUuXG5mdW5jdGlvbiB2YWxpZENodW5rKHN0cmVhbSwgc3RhdGUsIGNodW5rLCBjYikge1xuICB2YXIgdmFsaWQgPSB0cnVlO1xuICB2YXIgZXIgPSBmYWxzZTtcblxuICBpZiAoY2h1bmsgPT09IG51bGwpIHtcbiAgICBlciA9IG5ldyBUeXBlRXJyb3IoJ01heSBub3Qgd3JpdGUgbnVsbCB2YWx1ZXMgdG8gc3RyZWFtJyk7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGNodW5rICE9PSAnc3RyaW5nJyAmJiBjaHVuayAhPT0gdW5kZWZpbmVkICYmICFzdGF0ZS5vYmplY3RNb2RlKSB7XG4gICAgZXIgPSBuZXcgVHlwZUVycm9yKCdJbnZhbGlkIG5vbi1zdHJpbmcvYnVmZmVyIGNodW5rJyk7XG4gIH1cbiAgaWYgKGVyKSB7XG4gICAgc3RyZWFtLmVtaXQoJ2Vycm9yJywgZXIpO1xuICAgIHBuYS5uZXh0VGljayhjYiwgZXIpO1xuICAgIHZhbGlkID0gZmFsc2U7XG4gIH1cbiAgcmV0dXJuIHZhbGlkO1xufVxuXG5Xcml0YWJsZS5wcm90b3R5cGUud3JpdGUgPSBmdW5jdGlvbiAoY2h1bmssIGVuY29kaW5nLCBjYikge1xuICB2YXIgc3RhdGUgPSB0aGlzLl93cml0YWJsZVN0YXRlO1xuICB2YXIgcmV0ID0gZmFsc2U7XG4gIHZhciBpc0J1ZiA9ICFzdGF0ZS5vYmplY3RNb2RlICYmIF9pc1VpbnQ4QXJyYXkoY2h1bmspO1xuXG4gIGlmIChpc0J1ZiAmJiAhQnVmZmVyLmlzQnVmZmVyKGNodW5rKSkge1xuICAgIGNodW5rID0gX3VpbnQ4QXJyYXlUb0J1ZmZlcihjaHVuayk7XG4gIH1cblxuICBpZiAodHlwZW9mIGVuY29kaW5nID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY2IgPSBlbmNvZGluZztcbiAgICBlbmNvZGluZyA9IG51bGw7XG4gIH1cblxuICBpZiAoaXNCdWYpIGVuY29kaW5nID0gJ2J1ZmZlcic7ZWxzZSBpZiAoIWVuY29kaW5nKSBlbmNvZGluZyA9IHN0YXRlLmRlZmF1bHRFbmNvZGluZztcblxuICBpZiAodHlwZW9mIGNiICE9PSAnZnVuY3Rpb24nKSBjYiA9IG5vcDtcblxuICBpZiAoc3RhdGUuZW5kZWQpIHdyaXRlQWZ0ZXJFbmQodGhpcywgY2IpO2Vsc2UgaWYgKGlzQnVmIHx8IHZhbGlkQ2h1bmsodGhpcywgc3RhdGUsIGNodW5rLCBjYikpIHtcbiAgICBzdGF0ZS5wZW5kaW5nY2IrKztcbiAgICByZXQgPSB3cml0ZU9yQnVmZmVyKHRoaXMsIHN0YXRlLCBpc0J1ZiwgY2h1bmssIGVuY29kaW5nLCBjYik7XG4gIH1cblxuICByZXR1cm4gcmV0O1xufTtcblxuV3JpdGFibGUucHJvdG90eXBlLmNvcmsgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBzdGF0ZSA9IHRoaXMuX3dyaXRhYmxlU3RhdGU7XG5cbiAgc3RhdGUuY29ya2VkKys7XG59O1xuXG5Xcml0YWJsZS5wcm90b3R5cGUudW5jb3JrID0gZnVuY3Rpb24gKCkge1xuICB2YXIgc3RhdGUgPSB0aGlzLl93cml0YWJsZVN0YXRlO1xuXG4gIGlmIChzdGF0ZS5jb3JrZWQpIHtcbiAgICBzdGF0ZS5jb3JrZWQtLTtcblxuICAgIGlmICghc3RhdGUud3JpdGluZyAmJiAhc3RhdGUuY29ya2VkICYmICFzdGF0ZS5maW5pc2hlZCAmJiAhc3RhdGUuYnVmZmVyUHJvY2Vzc2luZyAmJiBzdGF0ZS5idWZmZXJlZFJlcXVlc3QpIGNsZWFyQnVmZmVyKHRoaXMsIHN0YXRlKTtcbiAgfVxufTtcblxuV3JpdGFibGUucHJvdG90eXBlLnNldERlZmF1bHRFbmNvZGluZyA9IGZ1bmN0aW9uIHNldERlZmF1bHRFbmNvZGluZyhlbmNvZGluZykge1xuICAvLyBub2RlOjpQYXJzZUVuY29kaW5nKCkgcmVxdWlyZXMgbG93ZXIgY2FzZS5cbiAgaWYgKHR5cGVvZiBlbmNvZGluZyA9PT0gJ3N0cmluZycpIGVuY29kaW5nID0gZW5jb2RpbmcudG9Mb3dlckNhc2UoKTtcbiAgaWYgKCEoWydoZXgnLCAndXRmOCcsICd1dGYtOCcsICdhc2NpaScsICdiaW5hcnknLCAnYmFzZTY0JywgJ3VjczInLCAndWNzLTInLCAndXRmMTZsZScsICd1dGYtMTZsZScsICdyYXcnXS5pbmRleE9mKChlbmNvZGluZyArICcnKS50b0xvd2VyQ2FzZSgpKSA+IC0xKSkgdGhyb3cgbmV3IFR5cGVFcnJvcignVW5rbm93biBlbmNvZGluZzogJyArIGVuY29kaW5nKTtcbiAgdGhpcy5fd3JpdGFibGVTdGF0ZS5kZWZhdWx0RW5jb2RpbmcgPSBlbmNvZGluZztcbiAgcmV0dXJuIHRoaXM7XG59O1xuXG5mdW5jdGlvbiBkZWNvZGVDaHVuayhzdGF0ZSwgY2h1bmssIGVuY29kaW5nKSB7XG4gIGlmICghc3RhdGUub2JqZWN0TW9kZSAmJiBzdGF0ZS5kZWNvZGVTdHJpbmdzICE9PSBmYWxzZSAmJiB0eXBlb2YgY2h1bmsgPT09ICdzdHJpbmcnKSB7XG4gICAgY2h1bmsgPSBCdWZmZXIuZnJvbShjaHVuaywgZW5jb2RpbmcpO1xuICB9XG4gIHJldHVybiBjaHVuaztcbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KFdyaXRhYmxlLnByb3RvdHlwZSwgJ3dyaXRhYmxlSGlnaFdhdGVyTWFyaycsIHtcbiAgLy8gbWFraW5nIGl0IGV4cGxpY2l0IHRoaXMgcHJvcGVydHkgaXMgbm90IGVudW1lcmFibGVcbiAgLy8gYmVjYXVzZSBvdGhlcndpc2Ugc29tZSBwcm90b3R5cGUgbWFuaXB1bGF0aW9uIGluXG4gIC8vIHVzZXJsYW5kIHdpbGwgZmFpbFxuICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgcmV0dXJuIHRoaXMuX3dyaXRhYmxlU3RhdGUuaGlnaFdhdGVyTWFyaztcbiAgfVxufSk7XG5cbi8vIGlmIHdlJ3JlIGFscmVhZHkgd3JpdGluZyBzb21ldGhpbmcsIHRoZW4ganVzdCBwdXQgdGhpc1xuLy8gaW4gdGhlIHF1ZXVlLCBhbmQgd2FpdCBvdXIgdHVybi4gIE90aGVyd2lzZSwgY2FsbCBfd3JpdGVcbi8vIElmIHdlIHJldHVybiBmYWxzZSwgdGhlbiB3ZSBuZWVkIGEgZHJhaW4gZXZlbnQsIHNvIHNldCB0aGF0IGZsYWcuXG5mdW5jdGlvbiB3cml0ZU9yQnVmZmVyKHN0cmVhbSwgc3RhdGUsIGlzQnVmLCBjaHVuaywgZW5jb2RpbmcsIGNiKSB7XG4gIGlmICghaXNCdWYpIHtcbiAgICB2YXIgbmV3Q2h1bmsgPSBkZWNvZGVDaHVuayhzdGF0ZSwgY2h1bmssIGVuY29kaW5nKTtcbiAgICBpZiAoY2h1bmsgIT09IG5ld0NodW5rKSB7XG4gICAgICBpc0J1ZiA9IHRydWU7XG4gICAgICBlbmNvZGluZyA9ICdidWZmZXInO1xuICAgICAgY2h1bmsgPSBuZXdDaHVuaztcbiAgICB9XG4gIH1cbiAgdmFyIGxlbiA9IHN0YXRlLm9iamVjdE1vZGUgPyAxIDogY2h1bmsubGVuZ3RoO1xuXG4gIHN0YXRlLmxlbmd0aCArPSBsZW47XG5cbiAgdmFyIHJldCA9IHN0YXRlLmxlbmd0aCA8IHN0YXRlLmhpZ2hXYXRlck1hcms7XG4gIC8vIHdlIG11c3QgZW5zdXJlIHRoYXQgcHJldmlvdXMgbmVlZERyYWluIHdpbGwgbm90IGJlIHJlc2V0IHRvIGZhbHNlLlxuICBpZiAoIXJldCkgc3RhdGUubmVlZERyYWluID0gdHJ1ZTtcblxuICBpZiAoc3RhdGUud3JpdGluZyB8fCBzdGF0ZS5jb3JrZWQpIHtcbiAgICB2YXIgbGFzdCA9IHN0YXRlLmxhc3RCdWZmZXJlZFJlcXVlc3Q7XG4gICAgc3RhdGUubGFzdEJ1ZmZlcmVkUmVxdWVzdCA9IHtcbiAgICAgIGNodW5rOiBjaHVuayxcbiAgICAgIGVuY29kaW5nOiBlbmNvZGluZyxcbiAgICAgIGlzQnVmOiBpc0J1ZixcbiAgICAgIGNhbGxiYWNrOiBjYixcbiAgICAgIG5leHQ6IG51bGxcbiAgICB9O1xuICAgIGlmIChsYXN0KSB7XG4gICAgICBsYXN0Lm5leHQgPSBzdGF0ZS5sYXN0QnVmZmVyZWRSZXF1ZXN0O1xuICAgIH0gZWxzZSB7XG4gICAgICBzdGF0ZS5idWZmZXJlZFJlcXVlc3QgPSBzdGF0ZS5sYXN0QnVmZmVyZWRSZXF1ZXN0O1xuICAgIH1cbiAgICBzdGF0ZS5idWZmZXJlZFJlcXVlc3RDb3VudCArPSAxO1xuICB9IGVsc2Uge1xuICAgIGRvV3JpdGUoc3RyZWFtLCBzdGF0ZSwgZmFsc2UsIGxlbiwgY2h1bmssIGVuY29kaW5nLCBjYik7XG4gIH1cblxuICByZXR1cm4gcmV0O1xufVxuXG5mdW5jdGlvbiBkb1dyaXRlKHN0cmVhbSwgc3RhdGUsIHdyaXRldiwgbGVuLCBjaHVuaywgZW5jb2RpbmcsIGNiKSB7XG4gIHN0YXRlLndyaXRlbGVuID0gbGVuO1xuICBzdGF0ZS53cml0ZWNiID0gY2I7XG4gIHN0YXRlLndyaXRpbmcgPSB0cnVlO1xuICBzdGF0ZS5zeW5jID0gdHJ1ZTtcbiAgaWYgKHdyaXRldikgc3RyZWFtLl93cml0ZXYoY2h1bmssIHN0YXRlLm9ud3JpdGUpO2Vsc2Ugc3RyZWFtLl93cml0ZShjaHVuaywgZW5jb2RpbmcsIHN0YXRlLm9ud3JpdGUpO1xuICBzdGF0ZS5zeW5jID0gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIG9ud3JpdGVFcnJvcihzdHJlYW0sIHN0YXRlLCBzeW5jLCBlciwgY2IpIHtcbiAgLS1zdGF0ZS5wZW5kaW5nY2I7XG5cbiAgaWYgKHN5bmMpIHtcbiAgICAvLyBkZWZlciB0aGUgY2FsbGJhY2sgaWYgd2UgYXJlIGJlaW5nIGNhbGxlZCBzeW5jaHJvbm91c2x5XG4gICAgLy8gdG8gYXZvaWQgcGlsaW5nIHVwIHRoaW5ncyBvbiB0aGUgc3RhY2tcbiAgICBwbmEubmV4dFRpY2soY2IsIGVyKTtcbiAgICAvLyB0aGlzIGNhbiBlbWl0IGZpbmlzaCwgYW5kIGl0IHdpbGwgYWx3YXlzIGhhcHBlblxuICAgIC8vIGFmdGVyIGVycm9yXG4gICAgcG5hLm5leHRUaWNrKGZpbmlzaE1heWJlLCBzdHJlYW0sIHN0YXRlKTtcbiAgICBzdHJlYW0uX3dyaXRhYmxlU3RhdGUuZXJyb3JFbWl0dGVkID0gdHJ1ZTtcbiAgICBzdHJlYW0uZW1pdCgnZXJyb3InLCBlcik7XG4gIH0gZWxzZSB7XG4gICAgLy8gdGhlIGNhbGxlciBleHBlY3QgdGhpcyB0byBoYXBwZW4gYmVmb3JlIGlmXG4gICAgLy8gaXQgaXMgYXN5bmNcbiAgICBjYihlcik7XG4gICAgc3RyZWFtLl93cml0YWJsZVN0YXRlLmVycm9yRW1pdHRlZCA9IHRydWU7XG4gICAgc3RyZWFtLmVtaXQoJ2Vycm9yJywgZXIpO1xuICAgIC8vIHRoaXMgY2FuIGVtaXQgZmluaXNoLCBidXQgZmluaXNoIG11c3RcbiAgICAvLyBhbHdheXMgZm9sbG93IGVycm9yXG4gICAgZmluaXNoTWF5YmUoc3RyZWFtLCBzdGF0ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gb253cml0ZVN0YXRlVXBkYXRlKHN0YXRlKSB7XG4gIHN0YXRlLndyaXRpbmcgPSBmYWxzZTtcbiAgc3RhdGUud3JpdGVjYiA9IG51bGw7XG4gIHN0YXRlLmxlbmd0aCAtPSBzdGF0ZS53cml0ZWxlbjtcbiAgc3RhdGUud3JpdGVsZW4gPSAwO1xufVxuXG5mdW5jdGlvbiBvbndyaXRlKHN0cmVhbSwgZXIpIHtcbiAgdmFyIHN0YXRlID0gc3RyZWFtLl93cml0YWJsZVN0YXRlO1xuICB2YXIgc3luYyA9IHN0YXRlLnN5bmM7XG4gIHZhciBjYiA9IHN0YXRlLndyaXRlY2I7XG5cbiAgb253cml0ZVN0YXRlVXBkYXRlKHN0YXRlKTtcblxuICBpZiAoZXIpIG9ud3JpdGVFcnJvcihzdHJlYW0sIHN0YXRlLCBzeW5jLCBlciwgY2IpO2Vsc2Uge1xuICAgIC8vIENoZWNrIGlmIHdlJ3JlIGFjdHVhbGx5IHJlYWR5IHRvIGZpbmlzaCwgYnV0IGRvbid0IGVtaXQgeWV0XG4gICAgdmFyIGZpbmlzaGVkID0gbmVlZEZpbmlzaChzdGF0ZSk7XG5cbiAgICBpZiAoIWZpbmlzaGVkICYmICFzdGF0ZS5jb3JrZWQgJiYgIXN0YXRlLmJ1ZmZlclByb2Nlc3NpbmcgJiYgc3RhdGUuYnVmZmVyZWRSZXF1ZXN0KSB7XG4gICAgICBjbGVhckJ1ZmZlcihzdHJlYW0sIHN0YXRlKTtcbiAgICB9XG5cbiAgICBpZiAoc3luYykge1xuICAgICAgLyo8cmVwbGFjZW1lbnQ+Ki9cbiAgICAgIGFzeW5jV3JpdGUoYWZ0ZXJXcml0ZSwgc3RyZWFtLCBzdGF0ZSwgZmluaXNoZWQsIGNiKTtcbiAgICAgIC8qPC9yZXBsYWNlbWVudD4qL1xuICAgIH0gZWxzZSB7XG4gICAgICBhZnRlcldyaXRlKHN0cmVhbSwgc3RhdGUsIGZpbmlzaGVkLCBjYik7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGFmdGVyV3JpdGUoc3RyZWFtLCBzdGF0ZSwgZmluaXNoZWQsIGNiKSB7XG4gIGlmICghZmluaXNoZWQpIG9ud3JpdGVEcmFpbihzdHJlYW0sIHN0YXRlKTtcbiAgc3RhdGUucGVuZGluZ2NiLS07XG4gIGNiKCk7XG4gIGZpbmlzaE1heWJlKHN0cmVhbSwgc3RhdGUpO1xufVxuXG4vLyBNdXN0IGZvcmNlIGNhbGxiYWNrIHRvIGJlIGNhbGxlZCBvbiBuZXh0VGljaywgc28gdGhhdCB3ZSBkb24ndFxuLy8gZW1pdCAnZHJhaW4nIGJlZm9yZSB0aGUgd3JpdGUoKSBjb25zdW1lciBnZXRzIHRoZSAnZmFsc2UnIHJldHVyblxuLy8gdmFsdWUsIGFuZCBoYXMgYSBjaGFuY2UgdG8gYXR0YWNoIGEgJ2RyYWluJyBsaXN0ZW5lci5cbmZ1bmN0aW9uIG9ud3JpdGVEcmFpbihzdHJlYW0sIHN0YXRlKSB7XG4gIGlmIChzdGF0ZS5sZW5ndGggPT09IDAgJiYgc3RhdGUubmVlZERyYWluKSB7XG4gICAgc3RhdGUubmVlZERyYWluID0gZmFsc2U7XG4gICAgc3RyZWFtLmVtaXQoJ2RyYWluJyk7XG4gIH1cbn1cblxuLy8gaWYgdGhlcmUncyBzb21ldGhpbmcgaW4gdGhlIGJ1ZmZlciB3YWl0aW5nLCB0aGVuIHByb2Nlc3MgaXRcbmZ1bmN0aW9uIGNsZWFyQnVmZmVyKHN0cmVhbSwgc3RhdGUpIHtcbiAgc3RhdGUuYnVmZmVyUHJvY2Vzc2luZyA9IHRydWU7XG4gIHZhciBlbnRyeSA9IHN0YXRlLmJ1ZmZlcmVkUmVxdWVzdDtcblxuICBpZiAoc3RyZWFtLl93cml0ZXYgJiYgZW50cnkgJiYgZW50cnkubmV4dCkge1xuICAgIC8vIEZhc3QgY2FzZSwgd3JpdGUgZXZlcnl0aGluZyB1c2luZyBfd3JpdGV2KClcbiAgICB2YXIgbCA9IHN0YXRlLmJ1ZmZlcmVkUmVxdWVzdENvdW50O1xuICAgIHZhciBidWZmZXIgPSBuZXcgQXJyYXkobCk7XG4gICAgdmFyIGhvbGRlciA9IHN0YXRlLmNvcmtlZFJlcXVlc3RzRnJlZTtcbiAgICBob2xkZXIuZW50cnkgPSBlbnRyeTtcblxuICAgIHZhciBjb3VudCA9IDA7XG4gICAgdmFyIGFsbEJ1ZmZlcnMgPSB0cnVlO1xuICAgIHdoaWxlIChlbnRyeSkge1xuICAgICAgYnVmZmVyW2NvdW50XSA9IGVudHJ5O1xuICAgICAgaWYgKCFlbnRyeS5pc0J1ZikgYWxsQnVmZmVycyA9IGZhbHNlO1xuICAgICAgZW50cnkgPSBlbnRyeS5uZXh0O1xuICAgICAgY291bnQgKz0gMTtcbiAgICB9XG4gICAgYnVmZmVyLmFsbEJ1ZmZlcnMgPSBhbGxCdWZmZXJzO1xuXG4gICAgZG9Xcml0ZShzdHJlYW0sIHN0YXRlLCB0cnVlLCBzdGF0ZS5sZW5ndGgsIGJ1ZmZlciwgJycsIGhvbGRlci5maW5pc2gpO1xuXG4gICAgLy8gZG9Xcml0ZSBpcyBhbG1vc3QgYWx3YXlzIGFzeW5jLCBkZWZlciB0aGVzZSB0byBzYXZlIGEgYml0IG9mIHRpbWVcbiAgICAvLyBhcyB0aGUgaG90IHBhdGggZW5kcyB3aXRoIGRvV3JpdGVcbiAgICBzdGF0ZS5wZW5kaW5nY2IrKztcbiAgICBzdGF0ZS5sYXN0QnVmZmVyZWRSZXF1ZXN0ID0gbnVsbDtcbiAgICBpZiAoaG9sZGVyLm5leHQpIHtcbiAgICAgIHN0YXRlLmNvcmtlZFJlcXVlc3RzRnJlZSA9IGhvbGRlci5uZXh0O1xuICAgICAgaG9sZGVyLm5leHQgPSBudWxsO1xuICAgIH0gZWxzZSB7XG4gICAgICBzdGF0ZS5jb3JrZWRSZXF1ZXN0c0ZyZWUgPSBuZXcgQ29ya2VkUmVxdWVzdChzdGF0ZSk7XG4gICAgfVxuICAgIHN0YXRlLmJ1ZmZlcmVkUmVxdWVzdENvdW50ID0gMDtcbiAgfSBlbHNlIHtcbiAgICAvLyBTbG93IGNhc2UsIHdyaXRlIGNodW5rcyBvbmUtYnktb25lXG4gICAgd2hpbGUgKGVudHJ5KSB7XG4gICAgICB2YXIgY2h1bmsgPSBlbnRyeS5jaHVuaztcbiAgICAgIHZhciBlbmNvZGluZyA9IGVudHJ5LmVuY29kaW5nO1xuICAgICAgdmFyIGNiID0gZW50cnkuY2FsbGJhY2s7XG4gICAgICB2YXIgbGVuID0gc3RhdGUub2JqZWN0TW9kZSA/IDEgOiBjaHVuay5sZW5ndGg7XG5cbiAgICAgIGRvV3JpdGUoc3RyZWFtLCBzdGF0ZSwgZmFsc2UsIGxlbiwgY2h1bmssIGVuY29kaW5nLCBjYik7XG4gICAgICBlbnRyeSA9IGVudHJ5Lm5leHQ7XG4gICAgICBzdGF0ZS5idWZmZXJlZFJlcXVlc3RDb3VudC0tO1xuICAgICAgLy8gaWYgd2UgZGlkbid0IGNhbGwgdGhlIG9ud3JpdGUgaW1tZWRpYXRlbHksIHRoZW5cbiAgICAgIC8vIGl0IG1lYW5zIHRoYXQgd2UgbmVlZCB0byB3YWl0IHVudGlsIGl0IGRvZXMuXG4gICAgICAvLyBhbHNvLCB0aGF0IG1lYW5zIHRoYXQgdGhlIGNodW5rIGFuZCBjYiBhcmUgY3VycmVudGx5XG4gICAgICAvLyBiZWluZyBwcm9jZXNzZWQsIHNvIG1vdmUgdGhlIGJ1ZmZlciBjb3VudGVyIHBhc3QgdGhlbS5cbiAgICAgIGlmIChzdGF0ZS53cml0aW5nKSB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChlbnRyeSA9PT0gbnVsbCkgc3RhdGUubGFzdEJ1ZmZlcmVkUmVxdWVzdCA9IG51bGw7XG4gIH1cblxuICBzdGF0ZS5idWZmZXJlZFJlcXVlc3QgPSBlbnRyeTtcbiAgc3RhdGUuYnVmZmVyUHJvY2Vzc2luZyA9IGZhbHNlO1xufVxuXG5Xcml0YWJsZS5wcm90b3R5cGUuX3dyaXRlID0gZnVuY3Rpb24gKGNodW5rLCBlbmNvZGluZywgY2IpIHtcbiAgY2IobmV3IEVycm9yKCdfd3JpdGUoKSBpcyBub3QgaW1wbGVtZW50ZWQnKSk7XG59O1xuXG5Xcml0YWJsZS5wcm90b3R5cGUuX3dyaXRldiA9IG51bGw7XG5cbldyaXRhYmxlLnByb3RvdHlwZS5lbmQgPSBmdW5jdGlvbiAoY2h1bmssIGVuY29kaW5nLCBjYikge1xuICB2YXIgc3RhdGUgPSB0aGlzLl93cml0YWJsZVN0YXRlO1xuXG4gIGlmICh0eXBlb2YgY2h1bmsgPT09ICdmdW5jdGlvbicpIHtcbiAgICBjYiA9IGNodW5rO1xuICAgIGNodW5rID0gbnVsbDtcbiAgICBlbmNvZGluZyA9IG51bGw7XG4gIH0gZWxzZSBpZiAodHlwZW9mIGVuY29kaW5nID09PSAnZnVuY3Rpb24nKSB7XG4gICAgY2IgPSBlbmNvZGluZztcbiAgICBlbmNvZGluZyA9IG51bGw7XG4gIH1cblxuICBpZiAoY2h1bmsgIT09IG51bGwgJiYgY2h1bmsgIT09IHVuZGVmaW5lZCkgdGhpcy53cml0ZShjaHVuaywgZW5jb2RpbmcpO1xuXG4gIC8vIC5lbmQoKSBmdWxseSB1bmNvcmtzXG4gIGlmIChzdGF0ZS5jb3JrZWQpIHtcbiAgICBzdGF0ZS5jb3JrZWQgPSAxO1xuICAgIHRoaXMudW5jb3JrKCk7XG4gIH1cblxuICAvLyBpZ25vcmUgdW5uZWNlc3NhcnkgZW5kKCkgY2FsbHMuXG4gIGlmICghc3RhdGUuZW5kaW5nICYmICFzdGF0ZS5maW5pc2hlZCkgZW5kV3JpdGFibGUodGhpcywgc3RhdGUsIGNiKTtcbn07XG5cbmZ1bmN0aW9uIG5lZWRGaW5pc2goc3RhdGUpIHtcbiAgcmV0dXJuIHN0YXRlLmVuZGluZyAmJiBzdGF0ZS5sZW5ndGggPT09IDAgJiYgc3RhdGUuYnVmZmVyZWRSZXF1ZXN0ID09PSBudWxsICYmICFzdGF0ZS5maW5pc2hlZCAmJiAhc3RhdGUud3JpdGluZztcbn1cbmZ1bmN0aW9uIGNhbGxGaW5hbChzdHJlYW0sIHN0YXRlKSB7XG4gIHN0cmVhbS5fZmluYWwoZnVuY3Rpb24gKGVycikge1xuICAgIHN0YXRlLnBlbmRpbmdjYi0tO1xuICAgIGlmIChlcnIpIHtcbiAgICAgIHN0cmVhbS5lbWl0KCdlcnJvcicsIGVycik7XG4gICAgfVxuICAgIHN0YXRlLnByZWZpbmlzaGVkID0gdHJ1ZTtcbiAgICBzdHJlYW0uZW1pdCgncHJlZmluaXNoJyk7XG4gICAgZmluaXNoTWF5YmUoc3RyZWFtLCBzdGF0ZSk7XG4gIH0pO1xufVxuZnVuY3Rpb24gcHJlZmluaXNoKHN0cmVhbSwgc3RhdGUpIHtcbiAgaWYgKCFzdGF0ZS5wcmVmaW5pc2hlZCAmJiAhc3RhdGUuZmluYWxDYWxsZWQpIHtcbiAgICBpZiAodHlwZW9mIHN0cmVhbS5fZmluYWwgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgIHN0YXRlLnBlbmRpbmdjYisrO1xuICAgICAgc3RhdGUuZmluYWxDYWxsZWQgPSB0cnVlO1xuICAgICAgcG5hLm5leHRUaWNrKGNhbGxGaW5hbCwgc3RyZWFtLCBzdGF0ZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0YXRlLnByZWZpbmlzaGVkID0gdHJ1ZTtcbiAgICAgIHN0cmVhbS5lbWl0KCdwcmVmaW5pc2gnKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZmluaXNoTWF5YmUoc3RyZWFtLCBzdGF0ZSkge1xuICB2YXIgbmVlZCA9IG5lZWRGaW5pc2goc3RhdGUpO1xuICBpZiAobmVlZCkge1xuICAgIHByZWZpbmlzaChzdHJlYW0sIHN0YXRlKTtcbiAgICBpZiAoc3RhdGUucGVuZGluZ2NiID09PSAwKSB7XG4gICAgICBzdGF0ZS5maW5pc2hlZCA9IHRydWU7XG4gICAgICBzdHJlYW0uZW1pdCgnZmluaXNoJyk7XG4gICAgfVxuICB9XG4gIHJldHVybiBuZWVkO1xufVxuXG5mdW5jdGlvbiBlbmRXcml0YWJsZShzdHJlYW0sIHN0YXRlLCBjYikge1xuICBzdGF0ZS5lbmRpbmcgPSB0cnVlO1xuICBmaW5pc2hNYXliZShzdHJlYW0sIHN0YXRlKTtcbiAgaWYgKGNiKSB7XG4gICAgaWYgKHN0YXRlLmZpbmlzaGVkKSBwbmEubmV4dFRpY2soY2IpO2Vsc2Ugc3RyZWFtLm9uY2UoJ2ZpbmlzaCcsIGNiKTtcbiAgfVxuICBzdGF0ZS5lbmRlZCA9IHRydWU7XG4gIHN0cmVhbS53cml0YWJsZSA9IGZhbHNlO1xufVxuXG5mdW5jdGlvbiBvbkNvcmtlZEZpbmlzaChjb3JrUmVxLCBzdGF0ZSwgZXJyKSB7XG4gIHZhciBlbnRyeSA9IGNvcmtSZXEuZW50cnk7XG4gIGNvcmtSZXEuZW50cnkgPSBudWxsO1xuICB3aGlsZSAoZW50cnkpIHtcbiAgICB2YXIgY2IgPSBlbnRyeS5jYWxsYmFjaztcbiAgICBzdGF0ZS5wZW5kaW5nY2ItLTtcbiAgICBjYihlcnIpO1xuICAgIGVudHJ5ID0gZW50cnkubmV4dDtcbiAgfVxuICBpZiAoc3RhdGUuY29ya2VkUmVxdWVzdHNGcmVlKSB7XG4gICAgc3RhdGUuY29ya2VkUmVxdWVzdHNGcmVlLm5leHQgPSBjb3JrUmVxO1xuICB9IGVsc2Uge1xuICAgIHN0YXRlLmNvcmtlZFJlcXVlc3RzRnJlZSA9IGNvcmtSZXE7XG4gIH1cbn1cblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KFdyaXRhYmxlLnByb3RvdHlwZSwgJ2Rlc3Ryb3llZCcsIHtcbiAgZ2V0OiBmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHRoaXMuX3dyaXRhYmxlU3RhdGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcy5fd3JpdGFibGVTdGF0ZS5kZXN0cm95ZWQ7XG4gIH0sXG4gIHNldDogZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgLy8gd2UgaWdub3JlIHRoZSB2YWx1ZSBpZiB0aGUgc3RyZWFtXG4gICAgLy8gaGFzIG5vdCBiZWVuIGluaXRpYWxpemVkIHlldFxuICAgIGlmICghdGhpcy5fd3JpdGFibGVTdGF0ZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIGJhY2t3YXJkIGNvbXBhdGliaWxpdHksIHRoZSB1c2VyIGlzIGV4cGxpY2l0bHlcbiAgICAvLyBtYW5hZ2luZyBkZXN0cm95ZWRcbiAgICB0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZCA9IHZhbHVlO1xuICB9XG59KTtcblxuV3JpdGFibGUucHJvdG90eXBlLmRlc3Ryb3kgPSBkZXN0cm95SW1wbC5kZXN0cm95O1xuV3JpdGFibGUucHJvdG90eXBlLl91bmRlc3Ryb3kgPSBkZXN0cm95SW1wbC51bmRlc3Ryb3k7XG5Xcml0YWJsZS5wcm90b3R5cGUuX2Rlc3Ryb3kgPSBmdW5jdGlvbiAoZXJyLCBjYikge1xuICB0aGlzLmVuZCgpO1xuICBjYihlcnIpO1xufTsiLCIndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbnZhciBCdWZmZXIgPSByZXF1aXJlKCdzYWZlLWJ1ZmZlcicpLkJ1ZmZlcjtcbnZhciB1dGlsID0gcmVxdWlyZSgndXRpbCcpO1xuXG5mdW5jdGlvbiBjb3B5QnVmZmVyKHNyYywgdGFyZ2V0LCBvZmZzZXQpIHtcbiAgc3JjLmNvcHkodGFyZ2V0LCBvZmZzZXQpO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uICgpIHtcbiAgZnVuY3Rpb24gQnVmZmVyTGlzdCgpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgQnVmZmVyTGlzdCk7XG5cbiAgICB0aGlzLmhlYWQgPSBudWxsO1xuICAgIHRoaXMudGFpbCA9IG51bGw7XG4gICAgdGhpcy5sZW5ndGggPSAwO1xuICB9XG5cbiAgQnVmZmVyTGlzdC5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uIHB1c2godikge1xuICAgIHZhciBlbnRyeSA9IHsgZGF0YTogdiwgbmV4dDogbnVsbCB9O1xuICAgIGlmICh0aGlzLmxlbmd0aCA+IDApIHRoaXMudGFpbC5uZXh0ID0gZW50cnk7ZWxzZSB0aGlzLmhlYWQgPSBlbnRyeTtcbiAgICB0aGlzLnRhaWwgPSBlbnRyeTtcbiAgICArK3RoaXMubGVuZ3RoO1xuICB9O1xuXG4gIEJ1ZmZlckxpc3QucHJvdG90eXBlLnVuc2hpZnQgPSBmdW5jdGlvbiB1bnNoaWZ0KHYpIHtcbiAgICB2YXIgZW50cnkgPSB7IGRhdGE6IHYsIG5leHQ6IHRoaXMuaGVhZCB9O1xuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgdGhpcy50YWlsID0gZW50cnk7XG4gICAgdGhpcy5oZWFkID0gZW50cnk7XG4gICAgKyt0aGlzLmxlbmd0aDtcbiAgfTtcblxuICBCdWZmZXJMaXN0LnByb3RvdHlwZS5zaGlmdCA9IGZ1bmN0aW9uIHNoaWZ0KCkge1xuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuO1xuICAgIHZhciByZXQgPSB0aGlzLmhlYWQuZGF0YTtcbiAgICBpZiAodGhpcy5sZW5ndGggPT09IDEpIHRoaXMuaGVhZCA9IHRoaXMudGFpbCA9IG51bGw7ZWxzZSB0aGlzLmhlYWQgPSB0aGlzLmhlYWQubmV4dDtcbiAgICAtLXRoaXMubGVuZ3RoO1xuICAgIHJldHVybiByZXQ7XG4gIH07XG5cbiAgQnVmZmVyTGlzdC5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiBjbGVhcigpIHtcbiAgICB0aGlzLmhlYWQgPSB0aGlzLnRhaWwgPSBudWxsO1xuICAgIHRoaXMubGVuZ3RoID0gMDtcbiAgfTtcblxuICBCdWZmZXJMaXN0LnByb3RvdHlwZS5qb2luID0gZnVuY3Rpb24gam9pbihzKSB7XG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSAwKSByZXR1cm4gJyc7XG4gICAgdmFyIHAgPSB0aGlzLmhlYWQ7XG4gICAgdmFyIHJldCA9ICcnICsgcC5kYXRhO1xuICAgIHdoaWxlIChwID0gcC5uZXh0KSB7XG4gICAgICByZXQgKz0gcyArIHAuZGF0YTtcbiAgICB9cmV0dXJuIHJldDtcbiAgfTtcblxuICBCdWZmZXJMaXN0LnByb3RvdHlwZS5jb25jYXQgPSBmdW5jdGlvbiBjb25jYXQobikge1xuICAgIGlmICh0aGlzLmxlbmd0aCA9PT0gMCkgcmV0dXJuIEJ1ZmZlci5hbGxvYygwKTtcbiAgICBpZiAodGhpcy5sZW5ndGggPT09IDEpIHJldHVybiB0aGlzLmhlYWQuZGF0YTtcbiAgICB2YXIgcmV0ID0gQnVmZmVyLmFsbG9jVW5zYWZlKG4gPj4+IDApO1xuICAgIHZhciBwID0gdGhpcy5oZWFkO1xuICAgIHZhciBpID0gMDtcbiAgICB3aGlsZSAocCkge1xuICAgICAgY29weUJ1ZmZlcihwLmRhdGEsIHJldCwgaSk7XG4gICAgICBpICs9IHAuZGF0YS5sZW5ndGg7XG4gICAgICBwID0gcC5uZXh0O1xuICAgIH1cbiAgICByZXR1cm4gcmV0O1xuICB9O1xuXG4gIHJldHVybiBCdWZmZXJMaXN0O1xufSgpO1xuXG5pZiAodXRpbCAmJiB1dGlsLmluc3BlY3QgJiYgdXRpbC5pbnNwZWN0LmN1c3RvbSkge1xuICBtb2R1bGUuZXhwb3J0cy5wcm90b3R5cGVbdXRpbC5pbnNwZWN0LmN1c3RvbV0gPSBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIG9iaiA9IHV0aWwuaW5zcGVjdCh7IGxlbmd0aDogdGhpcy5sZW5ndGggfSk7XG4gICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IubmFtZSArICcgJyArIG9iajtcbiAgfTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbi8qPHJlcGxhY2VtZW50PiovXG5cbnZhciBwbmEgPSByZXF1aXJlKCdwcm9jZXNzLW5leHRpY2stYXJncycpO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbi8vIHVuZG9jdW1lbnRlZCBjYigpIEFQSSwgbmVlZGVkIGZvciBjb3JlLCBub3QgZm9yIHB1YmxpYyBBUElcbmZ1bmN0aW9uIGRlc3Ryb3koZXJyLCBjYikge1xuICB2YXIgX3RoaXMgPSB0aGlzO1xuXG4gIHZhciByZWFkYWJsZURlc3Ryb3llZCA9IHRoaXMuX3JlYWRhYmxlU3RhdGUgJiYgdGhpcy5fcmVhZGFibGVTdGF0ZS5kZXN0cm95ZWQ7XG4gIHZhciB3cml0YWJsZURlc3Ryb3llZCA9IHRoaXMuX3dyaXRhYmxlU3RhdGUgJiYgdGhpcy5fd3JpdGFibGVTdGF0ZS5kZXN0cm95ZWQ7XG5cbiAgaWYgKHJlYWRhYmxlRGVzdHJveWVkIHx8IHdyaXRhYmxlRGVzdHJveWVkKSB7XG4gICAgaWYgKGNiKSB7XG4gICAgICBjYihlcnIpO1xuICAgIH0gZWxzZSBpZiAoZXJyICYmICghdGhpcy5fd3JpdGFibGVTdGF0ZSB8fCAhdGhpcy5fd3JpdGFibGVTdGF0ZS5lcnJvckVtaXR0ZWQpKSB7XG4gICAgICBwbmEubmV4dFRpY2soZW1pdEVycm9yTlQsIHRoaXMsIGVycik7XG4gICAgfVxuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLy8gd2Ugc2V0IGRlc3Ryb3llZCB0byB0cnVlIGJlZm9yZSBmaXJpbmcgZXJyb3IgY2FsbGJhY2tzIGluIG9yZGVyXG4gIC8vIHRvIG1ha2UgaXQgcmUtZW50cmFuY2Ugc2FmZSBpbiBjYXNlIGRlc3Ryb3koKSBpcyBjYWxsZWQgd2l0aGluIGNhbGxiYWNrc1xuXG4gIGlmICh0aGlzLl9yZWFkYWJsZVN0YXRlKSB7XG4gICAgdGhpcy5fcmVhZGFibGVTdGF0ZS5kZXN0cm95ZWQgPSB0cnVlO1xuICB9XG5cbiAgLy8gaWYgdGhpcyBpcyBhIGR1cGxleCBzdHJlYW0gbWFyayB0aGUgd3JpdGFibGUgcGFydCBhcyBkZXN0cm95ZWQgYXMgd2VsbFxuICBpZiAodGhpcy5fd3JpdGFibGVTdGF0ZSkge1xuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUuZGVzdHJveWVkID0gdHJ1ZTtcbiAgfVxuXG4gIHRoaXMuX2Rlc3Ryb3koZXJyIHx8IG51bGwsIGZ1bmN0aW9uIChlcnIpIHtcbiAgICBpZiAoIWNiICYmIGVycikge1xuICAgICAgcG5hLm5leHRUaWNrKGVtaXRFcnJvck5ULCBfdGhpcywgZXJyKTtcbiAgICAgIGlmIChfdGhpcy5fd3JpdGFibGVTdGF0ZSkge1xuICAgICAgICBfdGhpcy5fd3JpdGFibGVTdGF0ZS5lcnJvckVtaXR0ZWQgPSB0cnVlO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoY2IpIHtcbiAgICAgIGNiKGVycik7XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gdGhpcztcbn1cblxuZnVuY3Rpb24gdW5kZXN0cm95KCkge1xuICBpZiAodGhpcy5fcmVhZGFibGVTdGF0ZSkge1xuICAgIHRoaXMuX3JlYWRhYmxlU3RhdGUuZGVzdHJveWVkID0gZmFsc2U7XG4gICAgdGhpcy5fcmVhZGFibGVTdGF0ZS5yZWFkaW5nID0gZmFsc2U7XG4gICAgdGhpcy5fcmVhZGFibGVTdGF0ZS5lbmRlZCA9IGZhbHNlO1xuICAgIHRoaXMuX3JlYWRhYmxlU3RhdGUuZW5kRW1pdHRlZCA9IGZhbHNlO1xuICB9XG5cbiAgaWYgKHRoaXMuX3dyaXRhYmxlU3RhdGUpIHtcbiAgICB0aGlzLl93cml0YWJsZVN0YXRlLmRlc3Ryb3llZCA9IGZhbHNlO1xuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUuZW5kZWQgPSBmYWxzZTtcbiAgICB0aGlzLl93cml0YWJsZVN0YXRlLmVuZGluZyA9IGZhbHNlO1xuICAgIHRoaXMuX3dyaXRhYmxlU3RhdGUuZmluaXNoZWQgPSBmYWxzZTtcbiAgICB0aGlzLl93cml0YWJsZVN0YXRlLmVycm9yRW1pdHRlZCA9IGZhbHNlO1xuICB9XG59XG5cbmZ1bmN0aW9uIGVtaXRFcnJvck5UKHNlbGYsIGVycikge1xuICBzZWxmLmVtaXQoJ2Vycm9yJywgZXJyKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIGRlc3Ryb3k6IGRlc3Ryb3ksXG4gIHVuZGVzdHJveTogdW5kZXN0cm95XG59OyIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xuIiwibW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL3JlYWRhYmxlJykuUGFzc1Rocm91Z2hcbiIsImV4cG9ydHMgPSBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vbGliL19zdHJlYW1fcmVhZGFibGUuanMnKTtcbmV4cG9ydHMuU3RyZWFtID0gZXhwb3J0cztcbmV4cG9ydHMuUmVhZGFibGUgPSBleHBvcnRzO1xuZXhwb3J0cy5Xcml0YWJsZSA9IHJlcXVpcmUoJy4vbGliL19zdHJlYW1fd3JpdGFibGUuanMnKTtcbmV4cG9ydHMuRHVwbGV4ID0gcmVxdWlyZSgnLi9saWIvX3N0cmVhbV9kdXBsZXguanMnKTtcbmV4cG9ydHMuVHJhbnNmb3JtID0gcmVxdWlyZSgnLi9saWIvX3N0cmVhbV90cmFuc2Zvcm0uanMnKTtcbmV4cG9ydHMuUGFzc1Rocm91Z2ggPSByZXF1aXJlKCcuL2xpYi9fc3RyZWFtX3Bhc3N0aHJvdWdoLmpzJyk7XG4iLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vcmVhZGFibGUnKS5UcmFuc2Zvcm1cbiIsIm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9saWIvX3N0cmVhbV93cml0YWJsZS5qcycpO1xuIiwiJ3VzZSBzdHJpY3QnXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnYnVmZmVyJykuQnVmZmVyXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpXG52YXIgSGFzaEJhc2UgPSByZXF1aXJlKCdoYXNoLWJhc2UnKVxuXG52YXIgQVJSQVkxNiA9IG5ldyBBcnJheSgxNilcblxudmFyIHpsID0gW1xuICAwLCAxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LCAxMCwgMTEsIDEyLCAxMywgMTQsIDE1LFxuICA3LCA0LCAxMywgMSwgMTAsIDYsIDE1LCAzLCAxMiwgMCwgOSwgNSwgMiwgMTQsIDExLCA4LFxuICAzLCAxMCwgMTQsIDQsIDksIDE1LCA4LCAxLCAyLCA3LCAwLCA2LCAxMywgMTEsIDUsIDEyLFxuICAxLCA5LCAxMSwgMTAsIDAsIDgsIDEyLCA0LCAxMywgMywgNywgMTUsIDE0LCA1LCA2LCAyLFxuICA0LCAwLCA1LCA5LCA3LCAxMiwgMiwgMTAsIDE0LCAxLCAzLCA4LCAxMSwgNiwgMTUsIDEzXG5dXG5cbnZhciB6ciA9IFtcbiAgNSwgMTQsIDcsIDAsIDksIDIsIDExLCA0LCAxMywgNiwgMTUsIDgsIDEsIDEwLCAzLCAxMixcbiAgNiwgMTEsIDMsIDcsIDAsIDEzLCA1LCAxMCwgMTQsIDE1LCA4LCAxMiwgNCwgOSwgMSwgMixcbiAgMTUsIDUsIDEsIDMsIDcsIDE0LCA2LCA5LCAxMSwgOCwgMTIsIDIsIDEwLCAwLCA0LCAxMyxcbiAgOCwgNiwgNCwgMSwgMywgMTEsIDE1LCAwLCA1LCAxMiwgMiwgMTMsIDksIDcsIDEwLCAxNCxcbiAgMTIsIDE1LCAxMCwgNCwgMSwgNSwgOCwgNywgNiwgMiwgMTMsIDE0LCAwLCAzLCA5LCAxMVxuXVxuXG52YXIgc2wgPSBbXG4gIDExLCAxNCwgMTUsIDEyLCA1LCA4LCA3LCA5LCAxMSwgMTMsIDE0LCAxNSwgNiwgNywgOSwgOCxcbiAgNywgNiwgOCwgMTMsIDExLCA5LCA3LCAxNSwgNywgMTIsIDE1LCA5LCAxMSwgNywgMTMsIDEyLFxuICAxMSwgMTMsIDYsIDcsIDE0LCA5LCAxMywgMTUsIDE0LCA4LCAxMywgNiwgNSwgMTIsIDcsIDUsXG4gIDExLCAxMiwgMTQsIDE1LCAxNCwgMTUsIDksIDgsIDksIDE0LCA1LCA2LCA4LCA2LCA1LCAxMixcbiAgOSwgMTUsIDUsIDExLCA2LCA4LCAxMywgMTIsIDUsIDEyLCAxMywgMTQsIDExLCA4LCA1LCA2XG5dXG5cbnZhciBzciA9IFtcbiAgOCwgOSwgOSwgMTEsIDEzLCAxNSwgMTUsIDUsIDcsIDcsIDgsIDExLCAxNCwgMTQsIDEyLCA2LFxuICA5LCAxMywgMTUsIDcsIDEyLCA4LCA5LCAxMSwgNywgNywgMTIsIDcsIDYsIDE1LCAxMywgMTEsXG4gIDksIDcsIDE1LCAxMSwgOCwgNiwgNiwgMTQsIDEyLCAxMywgNSwgMTQsIDEzLCAxMywgNywgNSxcbiAgMTUsIDUsIDgsIDExLCAxNCwgMTQsIDYsIDE0LCA2LCA5LCAxMiwgOSwgMTIsIDUsIDE1LCA4LFxuICA4LCA1LCAxMiwgOSwgMTIsIDUsIDE0LCA2LCA4LCAxMywgNiwgNSwgMTUsIDEzLCAxMSwgMTFcbl1cblxudmFyIGhsID0gWzB4MDAwMDAwMDAsIDB4NWE4Mjc5OTksIDB4NmVkOWViYTEsIDB4OGYxYmJjZGMsIDB4YTk1M2ZkNGVdXG52YXIgaHIgPSBbMHg1MGEyOGJlNiwgMHg1YzRkZDEyNCwgMHg2ZDcwM2VmMywgMHg3YTZkNzZlOSwgMHgwMDAwMDAwMF1cblxuZnVuY3Rpb24gUklQRU1EMTYwICgpIHtcbiAgSGFzaEJhc2UuY2FsbCh0aGlzLCA2NClcblxuICAvLyBzdGF0ZVxuICB0aGlzLl9hID0gMHg2NzQ1MjMwMVxuICB0aGlzLl9iID0gMHhlZmNkYWI4OVxuICB0aGlzLl9jID0gMHg5OGJhZGNmZVxuICB0aGlzLl9kID0gMHgxMDMyNTQ3NlxuICB0aGlzLl9lID0gMHhjM2QyZTFmMFxufVxuXG5pbmhlcml0cyhSSVBFTUQxNjAsIEhhc2hCYXNlKVxuXG5SSVBFTUQxNjAucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gIHZhciB3b3JkcyA9IEFSUkFZMTZcbiAgZm9yICh2YXIgaiA9IDA7IGogPCAxNjsgKytqKSB3b3Jkc1tqXSA9IHRoaXMuX2Jsb2NrLnJlYWRJbnQzMkxFKGogKiA0KVxuXG4gIHZhciBhbCA9IHRoaXMuX2EgfCAwXG4gIHZhciBibCA9IHRoaXMuX2IgfCAwXG4gIHZhciBjbCA9IHRoaXMuX2MgfCAwXG4gIHZhciBkbCA9IHRoaXMuX2QgfCAwXG4gIHZhciBlbCA9IHRoaXMuX2UgfCAwXG5cbiAgdmFyIGFyID0gdGhpcy5fYSB8IDBcbiAgdmFyIGJyID0gdGhpcy5fYiB8IDBcbiAgdmFyIGNyID0gdGhpcy5fYyB8IDBcbiAgdmFyIGRyID0gdGhpcy5fZCB8IDBcbiAgdmFyIGVyID0gdGhpcy5fZSB8IDBcblxuICAvLyBjb21wdXRhdGlvblxuICBmb3IgKHZhciBpID0gMDsgaSA8IDgwOyBpICs9IDEpIHtcbiAgICB2YXIgdGxcbiAgICB2YXIgdHJcbiAgICBpZiAoaSA8IDE2KSB7XG4gICAgICB0bCA9IGZuMShhbCwgYmwsIGNsLCBkbCwgZWwsIHdvcmRzW3psW2ldXSwgaGxbMF0sIHNsW2ldKVxuICAgICAgdHIgPSBmbjUoYXIsIGJyLCBjciwgZHIsIGVyLCB3b3Jkc1t6cltpXV0sIGhyWzBdLCBzcltpXSlcbiAgICB9IGVsc2UgaWYgKGkgPCAzMikge1xuICAgICAgdGwgPSBmbjIoYWwsIGJsLCBjbCwgZGwsIGVsLCB3b3Jkc1t6bFtpXV0sIGhsWzFdLCBzbFtpXSlcbiAgICAgIHRyID0gZm40KGFyLCBiciwgY3IsIGRyLCBlciwgd29yZHNbenJbaV1dLCBoclsxXSwgc3JbaV0pXG4gICAgfSBlbHNlIGlmIChpIDwgNDgpIHtcbiAgICAgIHRsID0gZm4zKGFsLCBibCwgY2wsIGRsLCBlbCwgd29yZHNbemxbaV1dLCBobFsyXSwgc2xbaV0pXG4gICAgICB0ciA9IGZuMyhhciwgYnIsIGNyLCBkciwgZXIsIHdvcmRzW3pyW2ldXSwgaHJbMl0sIHNyW2ldKVxuICAgIH0gZWxzZSBpZiAoaSA8IDY0KSB7XG4gICAgICB0bCA9IGZuNChhbCwgYmwsIGNsLCBkbCwgZWwsIHdvcmRzW3psW2ldXSwgaGxbM10sIHNsW2ldKVxuICAgICAgdHIgPSBmbjIoYXIsIGJyLCBjciwgZHIsIGVyLCB3b3Jkc1t6cltpXV0sIGhyWzNdLCBzcltpXSlcbiAgICB9IGVsc2UgeyAvLyBpZiAoaTw4MCkge1xuICAgICAgdGwgPSBmbjUoYWwsIGJsLCBjbCwgZGwsIGVsLCB3b3Jkc1t6bFtpXV0sIGhsWzRdLCBzbFtpXSlcbiAgICAgIHRyID0gZm4xKGFyLCBiciwgY3IsIGRyLCBlciwgd29yZHNbenJbaV1dLCBocls0XSwgc3JbaV0pXG4gICAgfVxuXG4gICAgYWwgPSBlbFxuICAgIGVsID0gZGxcbiAgICBkbCA9IHJvdGwoY2wsIDEwKVxuICAgIGNsID0gYmxcbiAgICBibCA9IHRsXG5cbiAgICBhciA9IGVyXG4gICAgZXIgPSBkclxuICAgIGRyID0gcm90bChjciwgMTApXG4gICAgY3IgPSBiclxuICAgIGJyID0gdHJcbiAgfVxuXG4gIC8vIHVwZGF0ZSBzdGF0ZVxuICB2YXIgdCA9ICh0aGlzLl9iICsgY2wgKyBkcikgfCAwXG4gIHRoaXMuX2IgPSAodGhpcy5fYyArIGRsICsgZXIpIHwgMFxuICB0aGlzLl9jID0gKHRoaXMuX2QgKyBlbCArIGFyKSB8IDBcbiAgdGhpcy5fZCA9ICh0aGlzLl9lICsgYWwgKyBicikgfCAwXG4gIHRoaXMuX2UgPSAodGhpcy5fYSArIGJsICsgY3IpIHwgMFxuICB0aGlzLl9hID0gdFxufVxuXG5SSVBFTUQxNjAucHJvdG90eXBlLl9kaWdlc3QgPSBmdW5jdGlvbiAoKSB7XG4gIC8vIGNyZWF0ZSBwYWRkaW5nIGFuZCBoYW5kbGUgYmxvY2tzXG4gIHRoaXMuX2Jsb2NrW3RoaXMuX2Jsb2NrT2Zmc2V0KytdID0gMHg4MFxuICBpZiAodGhpcy5fYmxvY2tPZmZzZXQgPiA1Nikge1xuICAgIHRoaXMuX2Jsb2NrLmZpbGwoMCwgdGhpcy5fYmxvY2tPZmZzZXQsIDY0KVxuICAgIHRoaXMuX3VwZGF0ZSgpXG4gICAgdGhpcy5fYmxvY2tPZmZzZXQgPSAwXG4gIH1cblxuICB0aGlzLl9ibG9jay5maWxsKDAsIHRoaXMuX2Jsb2NrT2Zmc2V0LCA1NilcbiAgdGhpcy5fYmxvY2sud3JpdGVVSW50MzJMRSh0aGlzLl9sZW5ndGhbMF0sIDU2KVxuICB0aGlzLl9ibG9jay53cml0ZVVJbnQzMkxFKHRoaXMuX2xlbmd0aFsxXSwgNjApXG4gIHRoaXMuX3VwZGF0ZSgpXG5cbiAgLy8gcHJvZHVjZSByZXN1bHRcbiAgdmFyIGJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyA/IEJ1ZmZlci5hbGxvYygyMCkgOiBuZXcgQnVmZmVyKDIwKVxuICBidWZmZXIud3JpdGVJbnQzMkxFKHRoaXMuX2EsIDApXG4gIGJ1ZmZlci53cml0ZUludDMyTEUodGhpcy5fYiwgNClcbiAgYnVmZmVyLndyaXRlSW50MzJMRSh0aGlzLl9jLCA4KVxuICBidWZmZXIud3JpdGVJbnQzMkxFKHRoaXMuX2QsIDEyKVxuICBidWZmZXIud3JpdGVJbnQzMkxFKHRoaXMuX2UsIDE2KVxuICByZXR1cm4gYnVmZmVyXG59XG5cbmZ1bmN0aW9uIHJvdGwgKHgsIG4pIHtcbiAgcmV0dXJuICh4IDw8IG4pIHwgKHggPj4+ICgzMiAtIG4pKVxufVxuXG5mdW5jdGlvbiBmbjEgKGEsIGIsIGMsIGQsIGUsIG0sIGssIHMpIHtcbiAgcmV0dXJuIChyb3RsKChhICsgKGIgXiBjIF4gZCkgKyBtICsgaykgfCAwLCBzKSArIGUpIHwgMFxufVxuXG5mdW5jdGlvbiBmbjIgKGEsIGIsIGMsIGQsIGUsIG0sIGssIHMpIHtcbiAgcmV0dXJuIChyb3RsKChhICsgKChiICYgYykgfCAoKH5iKSAmIGQpKSArIG0gKyBrKSB8IDAsIHMpICsgZSkgfCAwXG59XG5cbmZ1bmN0aW9uIGZuMyAoYSwgYiwgYywgZCwgZSwgbSwgaywgcykge1xuICByZXR1cm4gKHJvdGwoKGEgKyAoKGIgfCAofmMpKSBeIGQpICsgbSArIGspIHwgMCwgcykgKyBlKSB8IDBcbn1cblxuZnVuY3Rpb24gZm40IChhLCBiLCBjLCBkLCBlLCBtLCBrLCBzKSB7XG4gIHJldHVybiAocm90bCgoYSArICgoYiAmIGQpIHwgKGMgJiAofmQpKSkgKyBtICsgaykgfCAwLCBzKSArIGUpIHwgMFxufVxuXG5mdW5jdGlvbiBmbjUgKGEsIGIsIGMsIGQsIGUsIG0sIGssIHMpIHtcbiAgcmV0dXJuIChyb3RsKChhICsgKGIgXiAoYyB8ICh+ZCkpKSArIG0gKyBrKSB8IDAsIHMpICsgZSkgfCAwXG59XG5cbm1vZHVsZS5leHBvcnRzID0gUklQRU1EMTYwXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBub2RlL25vLWRlcHJlY2F0ZWQtYXBpICovXG52YXIgYnVmZmVyID0gcmVxdWlyZSgnYnVmZmVyJylcbnZhciBCdWZmZXIgPSBidWZmZXIuQnVmZmVyXG5cbi8vIGFsdGVybmF0aXZlIHRvIHVzaW5nIE9iamVjdC5rZXlzIGZvciBvbGQgYnJvd3NlcnNcbmZ1bmN0aW9uIGNvcHlQcm9wcyAoc3JjLCBkc3QpIHtcbiAgZm9yICh2YXIga2V5IGluIHNyYykge1xuICAgIGRzdFtrZXldID0gc3JjW2tleV1cbiAgfVxufVxuaWYgKEJ1ZmZlci5mcm9tICYmIEJ1ZmZlci5hbGxvYyAmJiBCdWZmZXIuYWxsb2NVbnNhZmUgJiYgQnVmZmVyLmFsbG9jVW5zYWZlU2xvdykge1xuICBtb2R1bGUuZXhwb3J0cyA9IGJ1ZmZlclxufSBlbHNlIHtcbiAgLy8gQ29weSBwcm9wZXJ0aWVzIGZyb20gcmVxdWlyZSgnYnVmZmVyJylcbiAgY29weVByb3BzKGJ1ZmZlciwgZXhwb3J0cylcbiAgZXhwb3J0cy5CdWZmZXIgPSBTYWZlQnVmZmVyXG59XG5cbmZ1bmN0aW9uIFNhZmVCdWZmZXIgKGFyZywgZW5jb2RpbmdPck9mZnNldCwgbGVuZ3RoKSB7XG4gIHJldHVybiBCdWZmZXIoYXJnLCBlbmNvZGluZ09yT2Zmc2V0LCBsZW5ndGgpXG59XG5cbi8vIENvcHkgc3RhdGljIG1ldGhvZHMgZnJvbSBCdWZmZXJcbmNvcHlQcm9wcyhCdWZmZXIsIFNhZmVCdWZmZXIpXG5cblNhZmVCdWZmZXIuZnJvbSA9IGZ1bmN0aW9uIChhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aCkge1xuICBpZiAodHlwZW9mIGFyZyA9PT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IG5vdCBiZSBhIG51bWJlcicpXG4gIH1cbiAgcmV0dXJuIEJ1ZmZlcihhcmcsIGVuY29kaW5nT3JPZmZzZXQsIGxlbmd0aClcbn1cblxuU2FmZUJ1ZmZlci5hbGxvYyA9IGZ1bmN0aW9uIChzaXplLCBmaWxsLCBlbmNvZGluZykge1xuICBpZiAodHlwZW9mIHNpemUgIT09ICdudW1iZXInKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignQXJndW1lbnQgbXVzdCBiZSBhIG51bWJlcicpXG4gIH1cbiAgdmFyIGJ1ZiA9IEJ1ZmZlcihzaXplKVxuICBpZiAoZmlsbCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgaWYgKHR5cGVvZiBlbmNvZGluZyA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGJ1Zi5maWxsKGZpbGwsIGVuY29kaW5nKVxuICAgIH0gZWxzZSB7XG4gICAgICBidWYuZmlsbChmaWxsKVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBidWYuZmlsbCgwKVxuICB9XG4gIHJldHVybiBidWZcbn1cblxuU2FmZUJ1ZmZlci5hbGxvY1Vuc2FmZSA9IGZ1bmN0aW9uIChzaXplKSB7XG4gIGlmICh0eXBlb2Ygc2l6ZSAhPT0gJ251bWJlcicpIHtcbiAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdBcmd1bWVudCBtdXN0IGJlIGEgbnVtYmVyJylcbiAgfVxuICByZXR1cm4gQnVmZmVyKHNpemUpXG59XG5cblNhZmVCdWZmZXIuYWxsb2NVbnNhZmVTbG93ID0gZnVuY3Rpb24gKHNpemUpIHtcbiAgaWYgKHR5cGVvZiBzaXplICE9PSAnbnVtYmVyJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0FyZ3VtZW50IG11c3QgYmUgYSBudW1iZXInKVxuICB9XG4gIHJldHVybiBidWZmZXIuU2xvd0J1ZmZlcihzaXplKVxufVxuIiwiIWZ1bmN0aW9uKGdsb2JhbHMpe1xuJ3VzZSBzdHJpY3QnXG5cbi8vKioqIFVNRCBCRUdJTlxuaWYgKHR5cGVvZiBkZWZpbmUgIT09ICd1bmRlZmluZWQnICYmIGRlZmluZS5hbWQpIHsgLy9yZXF1aXJlLmpzIC8gQU1EXG4gIGRlZmluZShbXSwgZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIHNlY3VyZVJhbmRvbVxuICB9KVxufSBlbHNlIGlmICh0eXBlb2YgbW9kdWxlICE9PSAndW5kZWZpbmVkJyAmJiBtb2R1bGUuZXhwb3J0cykgeyAvL0NvbW1vbkpTXG4gIG1vZHVsZS5leHBvcnRzID0gc2VjdXJlUmFuZG9tXG59IGVsc2UgeyAvL3NjcmlwdCAvIGJyb3dzZXJcbiAgZ2xvYmFscy5zZWN1cmVSYW5kb20gPSBzZWN1cmVSYW5kb21cbn1cbi8vKioqIFVNRCBFTkRcblxuLy9vcHRpb25zLnR5cGUgaXMgdGhlIG9ubHkgdmFsaWQgb3B0aW9uXG5mdW5jdGlvbiBzZWN1cmVSYW5kb20oY291bnQsIG9wdGlvbnMpIHtcbiAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge3R5cGU6ICdBcnJheSd9XG4gIC8vd2UgY2hlY2sgZm9yIHByb2Nlc3MucGlkIHRvIHByZXZlbnQgYnJvd3NlcmlmeSBmcm9tIHRyaWNraW5nIHVzXG4gIGlmICh0eXBlb2YgcHJvY2VzcyAhPSAndW5kZWZpbmVkJyAmJiB0eXBlb2YgcHJvY2Vzcy5waWQgPT0gJ251bWJlcicpIHtcbiAgICByZXR1cm4gbm9kZVJhbmRvbShjb3VudCwgb3B0aW9ucylcbiAgfSBlbHNlIHtcbiAgICB2YXIgY3J5cHRvID0gd2luZG93LmNyeXB0byB8fCB3aW5kb3cubXNDcnlwdG9cbiAgICBpZiAoIWNyeXB0bykgdGhyb3cgbmV3IEVycm9yKFwiWW91ciBicm93c2VyIGRvZXMgbm90IHN1cHBvcnQgd2luZG93LmNyeXB0by5cIilcbiAgICByZXR1cm4gYnJvd3NlclJhbmRvbShjb3VudCwgb3B0aW9ucylcbiAgfVxufVxuXG5mdW5jdGlvbiBub2RlUmFuZG9tKGNvdW50LCBvcHRpb25zKSB7XG4gIHZhciBjcnlwdG8gPSByZXF1aXJlKCdjcnlwdG8nKVxuICB2YXIgYnVmID0gY3J5cHRvLnJhbmRvbUJ5dGVzKGNvdW50KVxuXG4gIHN3aXRjaCAob3B0aW9ucy50eXBlKSB7XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgcmV0dXJuIFtdLnNsaWNlLmNhbGwoYnVmKVxuICAgIGNhc2UgJ0J1ZmZlcic6XG4gICAgICByZXR1cm4gYnVmXG4gICAgY2FzZSAnVWludDhBcnJheSc6XG4gICAgICB2YXIgYXJyID0gbmV3IFVpbnQ4QXJyYXkoY291bnQpXG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGNvdW50OyArK2kpIHsgYXJyW2ldID0gYnVmLnJlYWRVSW50OChpKSB9XG4gICAgICByZXR1cm4gYXJyXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihvcHRpb25zLnR5cGUgKyBcIiBpcyB1bnN1cHBvcnRlZC5cIilcbiAgfVxufVxuXG5mdW5jdGlvbiBicm93c2VyUmFuZG9tKGNvdW50LCBvcHRpb25zKSB7XG4gIHZhciBuYXRpdmVBcnIgPSBuZXcgVWludDhBcnJheShjb3VudClcbiAgdmFyIGNyeXB0byA9IHdpbmRvdy5jcnlwdG8gfHwgd2luZG93Lm1zQ3J5cHRvXG4gIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmF0aXZlQXJyKVxuXG4gIHN3aXRjaCAob3B0aW9ucy50eXBlKSB7XG4gICAgY2FzZSAnQXJyYXknOlxuICAgICAgcmV0dXJuIFtdLnNsaWNlLmNhbGwobmF0aXZlQXJyKVxuICAgIGNhc2UgJ0J1ZmZlcic6XG4gICAgICB0cnkgeyB2YXIgYiA9IG5ldyBCdWZmZXIoMSkgfSBjYXRjaChlKSB7IHRocm93IG5ldyBFcnJvcignQnVmZmVyIG5vdCBzdXBwb3J0ZWQgaW4gdGhpcyBlbnZpcm9ubWVudC4gVXNlIE5vZGUuanMgb3IgQnJvd3NlcmlmeSBmb3IgYnJvd3NlciBzdXBwb3J0LicpfVxuICAgICAgcmV0dXJuIG5ldyBCdWZmZXIobmF0aXZlQXJyKVxuICAgIGNhc2UgJ1VpbnQ4QXJyYXknOlxuICAgICAgcmV0dXJuIG5hdGl2ZUFyclxuICAgIGRlZmF1bHQ6XG4gICAgICB0aHJvdyBuZXcgRXJyb3Iob3B0aW9ucy50eXBlICsgXCIgaXMgdW5zdXBwb3J0ZWQuXCIpXG4gIH1cbn1cblxuc2VjdXJlUmFuZG9tLnJhbmRvbUFycmF5ID0gZnVuY3Rpb24oYnl0ZUNvdW50KSB7XG4gIHJldHVybiBzZWN1cmVSYW5kb20oYnl0ZUNvdW50LCB7dHlwZTogJ0FycmF5J30pXG59XG5cbnNlY3VyZVJhbmRvbS5yYW5kb21VaW50OEFycmF5ID0gZnVuY3Rpb24oYnl0ZUNvdW50KSB7XG4gIHJldHVybiBzZWN1cmVSYW5kb20oYnl0ZUNvdW50LCB7dHlwZTogJ1VpbnQ4QXJyYXknfSlcbn1cblxuc2VjdXJlUmFuZG9tLnJhbmRvbUJ1ZmZlciA9IGZ1bmN0aW9uKGJ5dGVDb3VudCkge1xuICByZXR1cm4gc2VjdXJlUmFuZG9tKGJ5dGVDb3VudCwge3R5cGU6ICdCdWZmZXInfSlcbn1cblxuXG59KHRoaXMpO1xuIiwidmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyXG5cbi8vIHByb3RvdHlwZSBjbGFzcyBmb3IgaGFzaCBmdW5jdGlvbnNcbmZ1bmN0aW9uIEhhc2ggKGJsb2NrU2l6ZSwgZmluYWxTaXplKSB7XG4gIHRoaXMuX2Jsb2NrID0gQnVmZmVyLmFsbG9jKGJsb2NrU2l6ZSlcbiAgdGhpcy5fZmluYWxTaXplID0gZmluYWxTaXplXG4gIHRoaXMuX2Jsb2NrU2l6ZSA9IGJsb2NrU2l6ZVxuICB0aGlzLl9sZW4gPSAwXG59XG5cbkhhc2gucHJvdG90eXBlLnVwZGF0ZSA9IGZ1bmN0aW9uIChkYXRhLCBlbmMpIHtcbiAgaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJykge1xuICAgIGVuYyA9IGVuYyB8fCAndXRmOCdcbiAgICBkYXRhID0gQnVmZmVyLmZyb20oZGF0YSwgZW5jKVxuICB9XG5cbiAgdmFyIGJsb2NrID0gdGhpcy5fYmxvY2tcbiAgdmFyIGJsb2NrU2l6ZSA9IHRoaXMuX2Jsb2NrU2l6ZVxuICB2YXIgbGVuZ3RoID0gZGF0YS5sZW5ndGhcbiAgdmFyIGFjY3VtID0gdGhpcy5fbGVuXG5cbiAgZm9yICh2YXIgb2Zmc2V0ID0gMDsgb2Zmc2V0IDwgbGVuZ3RoOykge1xuICAgIHZhciBhc3NpZ25lZCA9IGFjY3VtICUgYmxvY2tTaXplXG4gICAgdmFyIHJlbWFpbmRlciA9IE1hdGgubWluKGxlbmd0aCAtIG9mZnNldCwgYmxvY2tTaXplIC0gYXNzaWduZWQpXG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHJlbWFpbmRlcjsgaSsrKSB7XG4gICAgICBibG9ja1thc3NpZ25lZCArIGldID0gZGF0YVtvZmZzZXQgKyBpXVxuICAgIH1cblxuICAgIGFjY3VtICs9IHJlbWFpbmRlclxuICAgIG9mZnNldCArPSByZW1haW5kZXJcblxuICAgIGlmICgoYWNjdW0gJSBibG9ja1NpemUpID09PSAwKSB7XG4gICAgICB0aGlzLl91cGRhdGUoYmxvY2spXG4gICAgfVxuICB9XG5cbiAgdGhpcy5fbGVuICs9IGxlbmd0aFxuICByZXR1cm4gdGhpc1xufVxuXG5IYXNoLnByb3RvdHlwZS5kaWdlc3QgPSBmdW5jdGlvbiAoZW5jKSB7XG4gIHZhciByZW0gPSB0aGlzLl9sZW4gJSB0aGlzLl9ibG9ja1NpemVcblxuICB0aGlzLl9ibG9ja1tyZW1dID0gMHg4MFxuXG4gIC8vIHplcm8gKHJlbSArIDEpIHRyYWlsaW5nIGJpdHMsIHdoZXJlIChyZW0gKyAxKSBpcyB0aGUgc21hbGxlc3RcbiAgLy8gbm9uLW5lZ2F0aXZlIHNvbHV0aW9uIHRvIHRoZSBlcXVhdGlvbiAobGVuZ3RoICsgMSArIChyZW0gKyAxKSkgPT09IGZpbmFsU2l6ZSBtb2QgYmxvY2tTaXplXG4gIHRoaXMuX2Jsb2NrLmZpbGwoMCwgcmVtICsgMSlcblxuICBpZiAocmVtID49IHRoaXMuX2ZpbmFsU2l6ZSkge1xuICAgIHRoaXMuX3VwZGF0ZSh0aGlzLl9ibG9jaylcbiAgICB0aGlzLl9ibG9jay5maWxsKDApXG4gIH1cblxuICB2YXIgYml0cyA9IHRoaXMuX2xlbiAqIDhcblxuICAvLyB1aW50MzJcbiAgaWYgKGJpdHMgPD0gMHhmZmZmZmZmZikge1xuICAgIHRoaXMuX2Jsb2NrLndyaXRlVUludDMyQkUoYml0cywgdGhpcy5fYmxvY2tTaXplIC0gNClcblxuICAvLyB1aW50NjRcbiAgfSBlbHNlIHtcbiAgICB2YXIgbG93Qml0cyA9IChiaXRzICYgMHhmZmZmZmZmZikgPj4+IDBcbiAgICB2YXIgaGlnaEJpdHMgPSAoYml0cyAtIGxvd0JpdHMpIC8gMHgxMDAwMDAwMDBcblxuICAgIHRoaXMuX2Jsb2NrLndyaXRlVUludDMyQkUoaGlnaEJpdHMsIHRoaXMuX2Jsb2NrU2l6ZSAtIDgpXG4gICAgdGhpcy5fYmxvY2sud3JpdGVVSW50MzJCRShsb3dCaXRzLCB0aGlzLl9ibG9ja1NpemUgLSA0KVxuICB9XG5cbiAgdGhpcy5fdXBkYXRlKHRoaXMuX2Jsb2NrKVxuICB2YXIgaGFzaCA9IHRoaXMuX2hhc2goKVxuXG4gIHJldHVybiBlbmMgPyBoYXNoLnRvU3RyaW5nKGVuYykgOiBoYXNoXG59XG5cbkhhc2gucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbiAoKSB7XG4gIHRocm93IG5ldyBFcnJvcignX3VwZGF0ZSBtdXN0IGJlIGltcGxlbWVudGVkIGJ5IHN1YmNsYXNzJylcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBIYXNoXG4iLCJ2YXIgZXhwb3J0cyA9IG1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gU0hBIChhbGdvcml0aG0pIHtcbiAgYWxnb3JpdGhtID0gYWxnb3JpdGhtLnRvTG93ZXJDYXNlKClcblxuICB2YXIgQWxnb3JpdGhtID0gZXhwb3J0c1thbGdvcml0aG1dXG4gIGlmICghQWxnb3JpdGhtKSB0aHJvdyBuZXcgRXJyb3IoYWxnb3JpdGhtICsgJyBpcyBub3Qgc3VwcG9ydGVkICh3ZSBhY2NlcHQgcHVsbCByZXF1ZXN0cyknKVxuXG4gIHJldHVybiBuZXcgQWxnb3JpdGhtKClcbn1cblxuZXhwb3J0cy5zaGEgPSByZXF1aXJlKCcuL3NoYScpXG5leHBvcnRzLnNoYTEgPSByZXF1aXJlKCcuL3NoYTEnKVxuZXhwb3J0cy5zaGEyMjQgPSByZXF1aXJlKCcuL3NoYTIyNCcpXG5leHBvcnRzLnNoYTI1NiA9IHJlcXVpcmUoJy4vc2hhMjU2JylcbmV4cG9ydHMuc2hhMzg0ID0gcmVxdWlyZSgnLi9zaGEzODQnKVxuZXhwb3J0cy5zaGE1MTIgPSByZXF1aXJlKCcuL3NoYTUxMicpXG4iLCIvKlxuICogQSBKYXZhU2NyaXB0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBTZWN1cmUgSGFzaCBBbGdvcml0aG0sIFNIQS0wLCBhcyBkZWZpbmVkXG4gKiBpbiBGSVBTIFBVQiAxODAtMVxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBkZXJpdmVkIGZyb20gc2hhMS5qcyBvZiB0aGUgc2FtZSByZXBvc2l0b3J5LlxuICogVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBTSEEtMCBhbmQgU0hBLTEgaXMganVzdCBhIGJpdHdpc2Ugcm90YXRlIGxlZnRcbiAqIG9wZXJhdGlvbiB3YXMgYWRkZWQuXG4gKi9cblxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIEhhc2ggPSByZXF1aXJlKCcuL2hhc2gnKVxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyXG5cbnZhciBLID0gW1xuICAweDVhODI3OTk5LCAweDZlZDllYmExLCAweDhmMWJiY2RjIHwgMCwgMHhjYTYyYzFkNiB8IDBcbl1cblxudmFyIFcgPSBuZXcgQXJyYXkoODApXG5cbmZ1bmN0aW9uIFNoYSAoKSB7XG4gIHRoaXMuaW5pdCgpXG4gIHRoaXMuX3cgPSBXXG5cbiAgSGFzaC5jYWxsKHRoaXMsIDY0LCA1Nilcbn1cblxuaW5oZXJpdHMoU2hhLCBIYXNoKVxuXG5TaGEucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiAoKSB7XG4gIHRoaXMuX2EgPSAweDY3NDUyMzAxXG4gIHRoaXMuX2IgPSAweGVmY2RhYjg5XG4gIHRoaXMuX2MgPSAweDk4YmFkY2ZlXG4gIHRoaXMuX2QgPSAweDEwMzI1NDc2XG4gIHRoaXMuX2UgPSAweGMzZDJlMWYwXG5cbiAgcmV0dXJuIHRoaXNcbn1cblxuZnVuY3Rpb24gcm90bDUgKG51bSkge1xuICByZXR1cm4gKG51bSA8PCA1KSB8IChudW0gPj4+IDI3KVxufVxuXG5mdW5jdGlvbiByb3RsMzAgKG51bSkge1xuICByZXR1cm4gKG51bSA8PCAzMCkgfCAobnVtID4+PiAyKVxufVxuXG5mdW5jdGlvbiBmdCAocywgYiwgYywgZCkge1xuICBpZiAocyA9PT0gMCkgcmV0dXJuIChiICYgYykgfCAoKH5iKSAmIGQpXG4gIGlmIChzID09PSAyKSByZXR1cm4gKGIgJiBjKSB8IChiICYgZCkgfCAoYyAmIGQpXG4gIHJldHVybiBiIF4gYyBeIGRcbn1cblxuU2hhLnByb3RvdHlwZS5fdXBkYXRlID0gZnVuY3Rpb24gKE0pIHtcbiAgdmFyIFcgPSB0aGlzLl93XG5cbiAgdmFyIGEgPSB0aGlzLl9hIHwgMFxuICB2YXIgYiA9IHRoaXMuX2IgfCAwXG4gIHZhciBjID0gdGhpcy5fYyB8IDBcbiAgdmFyIGQgPSB0aGlzLl9kIHwgMFxuICB2YXIgZSA9IHRoaXMuX2UgfCAwXG5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCAxNjsgKytpKSBXW2ldID0gTS5yZWFkSW50MzJCRShpICogNClcbiAgZm9yICg7IGkgPCA4MDsgKytpKSBXW2ldID0gV1tpIC0gM10gXiBXW2kgLSA4XSBeIFdbaSAtIDE0XSBeIFdbaSAtIDE2XVxuXG4gIGZvciAodmFyIGogPSAwOyBqIDwgODA7ICsraikge1xuICAgIHZhciBzID0gfn4oaiAvIDIwKVxuICAgIHZhciB0ID0gKHJvdGw1KGEpICsgZnQocywgYiwgYywgZCkgKyBlICsgV1tqXSArIEtbc10pIHwgMFxuXG4gICAgZSA9IGRcbiAgICBkID0gY1xuICAgIGMgPSByb3RsMzAoYilcbiAgICBiID0gYVxuICAgIGEgPSB0XG4gIH1cblxuICB0aGlzLl9hID0gKGEgKyB0aGlzLl9hKSB8IDBcbiAgdGhpcy5fYiA9IChiICsgdGhpcy5fYikgfCAwXG4gIHRoaXMuX2MgPSAoYyArIHRoaXMuX2MpIHwgMFxuICB0aGlzLl9kID0gKGQgKyB0aGlzLl9kKSB8IDBcbiAgdGhpcy5fZSA9IChlICsgdGhpcy5fZSkgfCAwXG59XG5cblNoYS5wcm90b3R5cGUuX2hhc2ggPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBIID0gQnVmZmVyLmFsbG9jVW5zYWZlKDIwKVxuXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2EgfCAwLCAwKVxuICBILndyaXRlSW50MzJCRSh0aGlzLl9iIHwgMCwgNClcbiAgSC53cml0ZUludDMyQkUodGhpcy5fYyB8IDAsIDgpXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2QgfCAwLCAxMilcbiAgSC53cml0ZUludDMyQkUodGhpcy5fZSB8IDAsIDE2KVxuXG4gIHJldHVybiBIXG59XG5cbm1vZHVsZS5leHBvcnRzID0gU2hhXG4iLCIvKlxuICogQSBKYXZhU2NyaXB0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBTZWN1cmUgSGFzaCBBbGdvcml0aG0sIFNIQS0xLCBhcyBkZWZpbmVkXG4gKiBpbiBGSVBTIFBVQiAxODAtMVxuICogVmVyc2lvbiAyLjFhIENvcHlyaWdodCBQYXVsIEpvaG5zdG9uIDIwMDAgLSAyMDAyLlxuICogT3RoZXIgY29udHJpYnV0b3JzOiBHcmVnIEhvbHQsIEFuZHJldyBLZXBlcnQsIFlkbmFyLCBMb3N0aW5ldFxuICogRGlzdHJpYnV0ZWQgdW5kZXIgdGhlIEJTRCBMaWNlbnNlXG4gKiBTZWUgaHR0cDovL3BhamhvbWUub3JnLnVrL2NyeXB0L21kNSBmb3IgZGV0YWlscy5cbiAqL1xuXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpXG52YXIgSGFzaCA9IHJlcXVpcmUoJy4vaGFzaCcpXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnc2FmZS1idWZmZXInKS5CdWZmZXJcblxudmFyIEsgPSBbXG4gIDB4NWE4Mjc5OTksIDB4NmVkOWViYTEsIDB4OGYxYmJjZGMgfCAwLCAweGNhNjJjMWQ2IHwgMFxuXVxuXG52YXIgVyA9IG5ldyBBcnJheSg4MClcblxuZnVuY3Rpb24gU2hhMSAoKSB7XG4gIHRoaXMuaW5pdCgpXG4gIHRoaXMuX3cgPSBXXG5cbiAgSGFzaC5jYWxsKHRoaXMsIDY0LCA1Nilcbn1cblxuaW5oZXJpdHMoU2hhMSwgSGFzaClcblxuU2hhMS5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5fYSA9IDB4Njc0NTIzMDFcbiAgdGhpcy5fYiA9IDB4ZWZjZGFiODlcbiAgdGhpcy5fYyA9IDB4OThiYWRjZmVcbiAgdGhpcy5fZCA9IDB4MTAzMjU0NzZcbiAgdGhpcy5fZSA9IDB4YzNkMmUxZjBcblxuICByZXR1cm4gdGhpc1xufVxuXG5mdW5jdGlvbiByb3RsMSAobnVtKSB7XG4gIHJldHVybiAobnVtIDw8IDEpIHwgKG51bSA+Pj4gMzEpXG59XG5cbmZ1bmN0aW9uIHJvdGw1IChudW0pIHtcbiAgcmV0dXJuIChudW0gPDwgNSkgfCAobnVtID4+PiAyNylcbn1cblxuZnVuY3Rpb24gcm90bDMwIChudW0pIHtcbiAgcmV0dXJuIChudW0gPDwgMzApIHwgKG51bSA+Pj4gMilcbn1cblxuZnVuY3Rpb24gZnQgKHMsIGIsIGMsIGQpIHtcbiAgaWYgKHMgPT09IDApIHJldHVybiAoYiAmIGMpIHwgKCh+YikgJiBkKVxuICBpZiAocyA9PT0gMikgcmV0dXJuIChiICYgYykgfCAoYiAmIGQpIHwgKGMgJiBkKVxuICByZXR1cm4gYiBeIGMgXiBkXG59XG5cblNoYTEucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbiAoTSkge1xuICB2YXIgVyA9IHRoaXMuX3dcblxuICB2YXIgYSA9IHRoaXMuX2EgfCAwXG4gIHZhciBiID0gdGhpcy5fYiB8IDBcbiAgdmFyIGMgPSB0aGlzLl9jIHwgMFxuICB2YXIgZCA9IHRoaXMuX2QgfCAwXG4gIHZhciBlID0gdGhpcy5fZSB8IDBcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IDE2OyArK2kpIFdbaV0gPSBNLnJlYWRJbnQzMkJFKGkgKiA0KVxuICBmb3IgKDsgaSA8IDgwOyArK2kpIFdbaV0gPSByb3RsMShXW2kgLSAzXSBeIFdbaSAtIDhdIF4gV1tpIC0gMTRdIF4gV1tpIC0gMTZdKVxuXG4gIGZvciAodmFyIGogPSAwOyBqIDwgODA7ICsraikge1xuICAgIHZhciBzID0gfn4oaiAvIDIwKVxuICAgIHZhciB0ID0gKHJvdGw1KGEpICsgZnQocywgYiwgYywgZCkgKyBlICsgV1tqXSArIEtbc10pIHwgMFxuXG4gICAgZSA9IGRcbiAgICBkID0gY1xuICAgIGMgPSByb3RsMzAoYilcbiAgICBiID0gYVxuICAgIGEgPSB0XG4gIH1cblxuICB0aGlzLl9hID0gKGEgKyB0aGlzLl9hKSB8IDBcbiAgdGhpcy5fYiA9IChiICsgdGhpcy5fYikgfCAwXG4gIHRoaXMuX2MgPSAoYyArIHRoaXMuX2MpIHwgMFxuICB0aGlzLl9kID0gKGQgKyB0aGlzLl9kKSB8IDBcbiAgdGhpcy5fZSA9IChlICsgdGhpcy5fZSkgfCAwXG59XG5cblNoYTEucHJvdG90eXBlLl9oYXNoID0gZnVuY3Rpb24gKCkge1xuICB2YXIgSCA9IEJ1ZmZlci5hbGxvY1Vuc2FmZSgyMClcblxuICBILndyaXRlSW50MzJCRSh0aGlzLl9hIHwgMCwgMClcbiAgSC53cml0ZUludDMyQkUodGhpcy5fYiB8IDAsIDQpXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2MgfCAwLCA4KVxuICBILndyaXRlSW50MzJCRSh0aGlzLl9kIHwgMCwgMTIpXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2UgfCAwLCAxNilcblxuICByZXR1cm4gSFxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFNoYTFcbiIsIi8qKlxuICogQSBKYXZhU2NyaXB0IGltcGxlbWVudGF0aW9uIG9mIHRoZSBTZWN1cmUgSGFzaCBBbGdvcml0aG0sIFNIQS0yNTYsIGFzIGRlZmluZWRcbiAqIGluIEZJUFMgMTgwLTJcbiAqIFZlcnNpb24gMi4yLWJldGEgQ29weXJpZ2h0IEFuZ2VsIE1hcmluLCBQYXVsIEpvaG5zdG9uIDIwMDAgLSAyMDA5LlxuICogT3RoZXIgY29udHJpYnV0b3JzOiBHcmVnIEhvbHQsIEFuZHJldyBLZXBlcnQsIFlkbmFyLCBMb3N0aW5ldFxuICpcbiAqL1xuXG52YXIgaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpXG52YXIgU2hhMjU2ID0gcmVxdWlyZSgnLi9zaGEyNTYnKVxudmFyIEhhc2ggPSByZXF1aXJlKCcuL2hhc2gnKVxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyXG5cbnZhciBXID0gbmV3IEFycmF5KDY0KVxuXG5mdW5jdGlvbiBTaGEyMjQgKCkge1xuICB0aGlzLmluaXQoKVxuXG4gIHRoaXMuX3cgPSBXIC8vIG5ldyBBcnJheSg2NClcblxuICBIYXNoLmNhbGwodGhpcywgNjQsIDU2KVxufVxuXG5pbmhlcml0cyhTaGEyMjQsIFNoYTI1NilcblxuU2hhMjI0LnByb3RvdHlwZS5pbml0ID0gZnVuY3Rpb24gKCkge1xuICB0aGlzLl9hID0gMHhjMTA1OWVkOFxuICB0aGlzLl9iID0gMHgzNjdjZDUwN1xuICB0aGlzLl9jID0gMHgzMDcwZGQxN1xuICB0aGlzLl9kID0gMHhmNzBlNTkzOVxuICB0aGlzLl9lID0gMHhmZmMwMGIzMVxuICB0aGlzLl9mID0gMHg2ODU4MTUxMVxuICB0aGlzLl9nID0gMHg2NGY5OGZhN1xuICB0aGlzLl9oID0gMHhiZWZhNGZhNFxuXG4gIHJldHVybiB0aGlzXG59XG5cblNoYTIyNC5wcm90b3R5cGUuX2hhc2ggPSBmdW5jdGlvbiAoKSB7XG4gIHZhciBIID0gQnVmZmVyLmFsbG9jVW5zYWZlKDI4KVxuXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2EsIDApXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2IsIDQpXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2MsIDgpXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2QsIDEyKVxuICBILndyaXRlSW50MzJCRSh0aGlzLl9lLCAxNilcbiAgSC53cml0ZUludDMyQkUodGhpcy5fZiwgMjApXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2csIDI0KVxuXG4gIHJldHVybiBIXG59XG5cbm1vZHVsZS5leHBvcnRzID0gU2hhMjI0XG4iLCIvKipcbiAqIEEgSmF2YVNjcmlwdCBpbXBsZW1lbnRhdGlvbiBvZiB0aGUgU2VjdXJlIEhhc2ggQWxnb3JpdGhtLCBTSEEtMjU2LCBhcyBkZWZpbmVkXG4gKiBpbiBGSVBTIDE4MC0yXG4gKiBWZXJzaW9uIDIuMi1iZXRhIENvcHlyaWdodCBBbmdlbCBNYXJpbiwgUGF1bCBKb2huc3RvbiAyMDAwIC0gMjAwOS5cbiAqIE90aGVyIGNvbnRyaWJ1dG9yczogR3JlZyBIb2x0LCBBbmRyZXcgS2VwZXJ0LCBZZG5hciwgTG9zdGluZXRcbiAqXG4gKi9cblxudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKVxudmFyIEhhc2ggPSByZXF1aXJlKCcuL2hhc2gnKVxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyXG5cbnZhciBLID0gW1xuICAweDQyOEEyRjk4LCAweDcxMzc0NDkxLCAweEI1QzBGQkNGLCAweEU5QjVEQkE1LFxuICAweDM5NTZDMjVCLCAweDU5RjExMUYxLCAweDkyM0Y4MkE0LCAweEFCMUM1RUQ1LFxuICAweEQ4MDdBQTk4LCAweDEyODM1QjAxLCAweDI0MzE4NUJFLCAweDU1MEM3REMzLFxuICAweDcyQkU1RDc0LCAweDgwREVCMUZFLCAweDlCREMwNkE3LCAweEMxOUJGMTc0LFxuICAweEU0OUI2OUMxLCAweEVGQkU0Nzg2LCAweDBGQzE5REM2LCAweDI0MENBMUNDLFxuICAweDJERTkyQzZGLCAweDRBNzQ4NEFBLCAweDVDQjBBOURDLCAweDc2Rjk4OERBLFxuICAweDk4M0U1MTUyLCAweEE4MzFDNjZELCAweEIwMDMyN0M4LCAweEJGNTk3RkM3LFxuICAweEM2RTAwQkYzLCAweEQ1QTc5MTQ3LCAweDA2Q0E2MzUxLCAweDE0MjkyOTY3LFxuICAweDI3QjcwQTg1LCAweDJFMUIyMTM4LCAweDREMkM2REZDLCAweDUzMzgwRDEzLFxuICAweDY1MEE3MzU0LCAweDc2NkEwQUJCLCAweDgxQzJDOTJFLCAweDkyNzIyQzg1LFxuICAweEEyQkZFOEExLCAweEE4MUE2NjRCLCAweEMyNEI4QjcwLCAweEM3NkM1MUEzLFxuICAweEQxOTJFODE5LCAweEQ2OTkwNjI0LCAweEY0MEUzNTg1LCAweDEwNkFBMDcwLFxuICAweDE5QTRDMTE2LCAweDFFMzc2QzA4LCAweDI3NDg3NzRDLCAweDM0QjBCQ0I1LFxuICAweDM5MUMwQ0IzLCAweDRFRDhBQTRBLCAweDVCOUNDQTRGLCAweDY4MkU2RkYzLFxuICAweDc0OEY4MkVFLCAweDc4QTU2MzZGLCAweDg0Qzg3ODE0LCAweDhDQzcwMjA4LFxuICAweDkwQkVGRkZBLCAweEE0NTA2Q0VCLCAweEJFRjlBM0Y3LCAweEM2NzE3OEYyXG5dXG5cbnZhciBXID0gbmV3IEFycmF5KDY0KVxuXG5mdW5jdGlvbiBTaGEyNTYgKCkge1xuICB0aGlzLmluaXQoKVxuXG4gIHRoaXMuX3cgPSBXIC8vIG5ldyBBcnJheSg2NClcblxuICBIYXNoLmNhbGwodGhpcywgNjQsIDU2KVxufVxuXG5pbmhlcml0cyhTaGEyNTYsIEhhc2gpXG5cblNoYTI1Ni5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5fYSA9IDB4NmEwOWU2NjdcbiAgdGhpcy5fYiA9IDB4YmI2N2FlODVcbiAgdGhpcy5fYyA9IDB4M2M2ZWYzNzJcbiAgdGhpcy5fZCA9IDB4YTU0ZmY1M2FcbiAgdGhpcy5fZSA9IDB4NTEwZTUyN2ZcbiAgdGhpcy5fZiA9IDB4OWIwNTY4OGNcbiAgdGhpcy5fZyA9IDB4MWY4M2Q5YWJcbiAgdGhpcy5faCA9IDB4NWJlMGNkMTlcblxuICByZXR1cm4gdGhpc1xufVxuXG5mdW5jdGlvbiBjaCAoeCwgeSwgeikge1xuICByZXR1cm4geiBeICh4ICYgKHkgXiB6KSlcbn1cblxuZnVuY3Rpb24gbWFqICh4LCB5LCB6KSB7XG4gIHJldHVybiAoeCAmIHkpIHwgKHogJiAoeCB8IHkpKVxufVxuXG5mdW5jdGlvbiBzaWdtYTAgKHgpIHtcbiAgcmV0dXJuICh4ID4+PiAyIHwgeCA8PCAzMCkgXiAoeCA+Pj4gMTMgfCB4IDw8IDE5KSBeICh4ID4+PiAyMiB8IHggPDwgMTApXG59XG5cbmZ1bmN0aW9uIHNpZ21hMSAoeCkge1xuICByZXR1cm4gKHggPj4+IDYgfCB4IDw8IDI2KSBeICh4ID4+PiAxMSB8IHggPDwgMjEpIF4gKHggPj4+IDI1IHwgeCA8PCA3KVxufVxuXG5mdW5jdGlvbiBnYW1tYTAgKHgpIHtcbiAgcmV0dXJuICh4ID4+PiA3IHwgeCA8PCAyNSkgXiAoeCA+Pj4gMTggfCB4IDw8IDE0KSBeICh4ID4+PiAzKVxufVxuXG5mdW5jdGlvbiBnYW1tYTEgKHgpIHtcbiAgcmV0dXJuICh4ID4+PiAxNyB8IHggPDwgMTUpIF4gKHggPj4+IDE5IHwgeCA8PCAxMykgXiAoeCA+Pj4gMTApXG59XG5cblNoYTI1Ni5wcm90b3R5cGUuX3VwZGF0ZSA9IGZ1bmN0aW9uIChNKSB7XG4gIHZhciBXID0gdGhpcy5fd1xuXG4gIHZhciBhID0gdGhpcy5fYSB8IDBcbiAgdmFyIGIgPSB0aGlzLl9iIHwgMFxuICB2YXIgYyA9IHRoaXMuX2MgfCAwXG4gIHZhciBkID0gdGhpcy5fZCB8IDBcbiAgdmFyIGUgPSB0aGlzLl9lIHwgMFxuICB2YXIgZiA9IHRoaXMuX2YgfCAwXG4gIHZhciBnID0gdGhpcy5fZyB8IDBcbiAgdmFyIGggPSB0aGlzLl9oIHwgMFxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMTY7ICsraSkgV1tpXSA9IE0ucmVhZEludDMyQkUoaSAqIDQpXG4gIGZvciAoOyBpIDwgNjQ7ICsraSkgV1tpXSA9IChnYW1tYTEoV1tpIC0gMl0pICsgV1tpIC0gN10gKyBnYW1tYTAoV1tpIC0gMTVdKSArIFdbaSAtIDE2XSkgfCAwXG5cbiAgZm9yICh2YXIgaiA9IDA7IGogPCA2NDsgKytqKSB7XG4gICAgdmFyIFQxID0gKGggKyBzaWdtYTEoZSkgKyBjaChlLCBmLCBnKSArIEtbal0gKyBXW2pdKSB8IDBcbiAgICB2YXIgVDIgPSAoc2lnbWEwKGEpICsgbWFqKGEsIGIsIGMpKSB8IDBcblxuICAgIGggPSBnXG4gICAgZyA9IGZcbiAgICBmID0gZVxuICAgIGUgPSAoZCArIFQxKSB8IDBcbiAgICBkID0gY1xuICAgIGMgPSBiXG4gICAgYiA9IGFcbiAgICBhID0gKFQxICsgVDIpIHwgMFxuICB9XG5cbiAgdGhpcy5fYSA9IChhICsgdGhpcy5fYSkgfCAwXG4gIHRoaXMuX2IgPSAoYiArIHRoaXMuX2IpIHwgMFxuICB0aGlzLl9jID0gKGMgKyB0aGlzLl9jKSB8IDBcbiAgdGhpcy5fZCA9IChkICsgdGhpcy5fZCkgfCAwXG4gIHRoaXMuX2UgPSAoZSArIHRoaXMuX2UpIHwgMFxuICB0aGlzLl9mID0gKGYgKyB0aGlzLl9mKSB8IDBcbiAgdGhpcy5fZyA9IChnICsgdGhpcy5fZykgfCAwXG4gIHRoaXMuX2ggPSAoaCArIHRoaXMuX2gpIHwgMFxufVxuXG5TaGEyNTYucHJvdG90eXBlLl9oYXNoID0gZnVuY3Rpb24gKCkge1xuICB2YXIgSCA9IEJ1ZmZlci5hbGxvY1Vuc2FmZSgzMilcblxuICBILndyaXRlSW50MzJCRSh0aGlzLl9hLCAwKVxuICBILndyaXRlSW50MzJCRSh0aGlzLl9iLCA0KVxuICBILndyaXRlSW50MzJCRSh0aGlzLl9jLCA4KVxuICBILndyaXRlSW50MzJCRSh0aGlzLl9kLCAxMilcbiAgSC53cml0ZUludDMyQkUodGhpcy5fZSwgMTYpXG4gIEgud3JpdGVJbnQzMkJFKHRoaXMuX2YsIDIwKVxuICBILndyaXRlSW50MzJCRSh0aGlzLl9nLCAyNClcbiAgSC53cml0ZUludDMyQkUodGhpcy5faCwgMjgpXG5cbiAgcmV0dXJuIEhcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBTaGEyNTZcbiIsInZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJylcbnZhciBTSEE1MTIgPSByZXF1aXJlKCcuL3NoYTUxMicpXG52YXIgSGFzaCA9IHJlcXVpcmUoJy4vaGFzaCcpXG52YXIgQnVmZmVyID0gcmVxdWlyZSgnc2FmZS1idWZmZXInKS5CdWZmZXJcblxudmFyIFcgPSBuZXcgQXJyYXkoMTYwKVxuXG5mdW5jdGlvbiBTaGEzODQgKCkge1xuICB0aGlzLmluaXQoKVxuICB0aGlzLl93ID0gV1xuXG4gIEhhc2guY2FsbCh0aGlzLCAxMjgsIDExMilcbn1cblxuaW5oZXJpdHMoU2hhMzg0LCBTSEE1MTIpXG5cblNoYTM4NC5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5fYWggPSAweGNiYmI5ZDVkXG4gIHRoaXMuX2JoID0gMHg2MjlhMjkyYVxuICB0aGlzLl9jaCA9IDB4OTE1OTAxNWFcbiAgdGhpcy5fZGggPSAweDE1MmZlY2Q4XG4gIHRoaXMuX2VoID0gMHg2NzMzMjY2N1xuICB0aGlzLl9maCA9IDB4OGViNDRhODdcbiAgdGhpcy5fZ2ggPSAweGRiMGMyZTBkXG4gIHRoaXMuX2hoID0gMHg0N2I1NDgxZFxuXG4gIHRoaXMuX2FsID0gMHhjMTA1OWVkOFxuICB0aGlzLl9ibCA9IDB4MzY3Y2Q1MDdcbiAgdGhpcy5fY2wgPSAweDMwNzBkZDE3XG4gIHRoaXMuX2RsID0gMHhmNzBlNTkzOVxuICB0aGlzLl9lbCA9IDB4ZmZjMDBiMzFcbiAgdGhpcy5fZmwgPSAweDY4NTgxNTExXG4gIHRoaXMuX2dsID0gMHg2NGY5OGZhN1xuICB0aGlzLl9obCA9IDB4YmVmYTRmYTRcblxuICByZXR1cm4gdGhpc1xufVxuXG5TaGEzODQucHJvdG90eXBlLl9oYXNoID0gZnVuY3Rpb24gKCkge1xuICB2YXIgSCA9IEJ1ZmZlci5hbGxvY1Vuc2FmZSg0OClcblxuICBmdW5jdGlvbiB3cml0ZUludDY0QkUgKGgsIGwsIG9mZnNldCkge1xuICAgIEgud3JpdGVJbnQzMkJFKGgsIG9mZnNldClcbiAgICBILndyaXRlSW50MzJCRShsLCBvZmZzZXQgKyA0KVxuICB9XG5cbiAgd3JpdGVJbnQ2NEJFKHRoaXMuX2FoLCB0aGlzLl9hbCwgMClcbiAgd3JpdGVJbnQ2NEJFKHRoaXMuX2JoLCB0aGlzLl9ibCwgOClcbiAgd3JpdGVJbnQ2NEJFKHRoaXMuX2NoLCB0aGlzLl9jbCwgMTYpXG4gIHdyaXRlSW50NjRCRSh0aGlzLl9kaCwgdGhpcy5fZGwsIDI0KVxuICB3cml0ZUludDY0QkUodGhpcy5fZWgsIHRoaXMuX2VsLCAzMilcbiAgd3JpdGVJbnQ2NEJFKHRoaXMuX2ZoLCB0aGlzLl9mbCwgNDApXG5cbiAgcmV0dXJuIEhcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBTaGEzODRcbiIsInZhciBpbmhlcml0cyA9IHJlcXVpcmUoJ2luaGVyaXRzJylcbnZhciBIYXNoID0gcmVxdWlyZSgnLi9oYXNoJylcbnZhciBCdWZmZXIgPSByZXF1aXJlKCdzYWZlLWJ1ZmZlcicpLkJ1ZmZlclxuXG52YXIgSyA9IFtcbiAgMHg0MjhhMmY5OCwgMHhkNzI4YWUyMiwgMHg3MTM3NDQ5MSwgMHgyM2VmNjVjZCxcbiAgMHhiNWMwZmJjZiwgMHhlYzRkM2IyZiwgMHhlOWI1ZGJhNSwgMHg4MTg5ZGJiYyxcbiAgMHgzOTU2YzI1YiwgMHhmMzQ4YjUzOCwgMHg1OWYxMTFmMSwgMHhiNjA1ZDAxOSxcbiAgMHg5MjNmODJhNCwgMHhhZjE5NGY5YiwgMHhhYjFjNWVkNSwgMHhkYTZkODExOCxcbiAgMHhkODA3YWE5OCwgMHhhMzAzMDI0MiwgMHgxMjgzNWIwMSwgMHg0NTcwNmZiZSxcbiAgMHgyNDMxODViZSwgMHg0ZWU0YjI4YywgMHg1NTBjN2RjMywgMHhkNWZmYjRlMixcbiAgMHg3MmJlNWQ3NCwgMHhmMjdiODk2ZiwgMHg4MGRlYjFmZSwgMHgzYjE2OTZiMSxcbiAgMHg5YmRjMDZhNywgMHgyNWM3MTIzNSwgMHhjMTliZjE3NCwgMHhjZjY5MjY5NCxcbiAgMHhlNDliNjljMSwgMHg5ZWYxNGFkMiwgMHhlZmJlNDc4NiwgMHgzODRmMjVlMyxcbiAgMHgwZmMxOWRjNiwgMHg4YjhjZDViNSwgMHgyNDBjYTFjYywgMHg3N2FjOWM2NSxcbiAgMHgyZGU5MmM2ZiwgMHg1OTJiMDI3NSwgMHg0YTc0ODRhYSwgMHg2ZWE2ZTQ4MyxcbiAgMHg1Y2IwYTlkYywgMHhiZDQxZmJkNCwgMHg3NmY5ODhkYSwgMHg4MzExNTNiNSxcbiAgMHg5ODNlNTE1MiwgMHhlZTY2ZGZhYiwgMHhhODMxYzY2ZCwgMHgyZGI0MzIxMCxcbiAgMHhiMDAzMjdjOCwgMHg5OGZiMjEzZiwgMHhiZjU5N2ZjNywgMHhiZWVmMGVlNCxcbiAgMHhjNmUwMGJmMywgMHgzZGE4OGZjMiwgMHhkNWE3OTE0NywgMHg5MzBhYTcyNSxcbiAgMHgwNmNhNjM1MSwgMHhlMDAzODI2ZiwgMHgxNDI5Mjk2NywgMHgwYTBlNmU3MCxcbiAgMHgyN2I3MGE4NSwgMHg0NmQyMmZmYywgMHgyZTFiMjEzOCwgMHg1YzI2YzkyNixcbiAgMHg0ZDJjNmRmYywgMHg1YWM0MmFlZCwgMHg1MzM4MGQxMywgMHg5ZDk1YjNkZixcbiAgMHg2NTBhNzM1NCwgMHg4YmFmNjNkZSwgMHg3NjZhMGFiYiwgMHgzYzc3YjJhOCxcbiAgMHg4MWMyYzkyZSwgMHg0N2VkYWVlNiwgMHg5MjcyMmM4NSwgMHgxNDgyMzUzYixcbiAgMHhhMmJmZThhMSwgMHg0Y2YxMDM2NCwgMHhhODFhNjY0YiwgMHhiYzQyMzAwMSxcbiAgMHhjMjRiOGI3MCwgMHhkMGY4OTc5MSwgMHhjNzZjNTFhMywgMHgwNjU0YmUzMCxcbiAgMHhkMTkyZTgxOSwgMHhkNmVmNTIxOCwgMHhkNjk5MDYyNCwgMHg1NTY1YTkxMCxcbiAgMHhmNDBlMzU4NSwgMHg1NzcxMjAyYSwgMHgxMDZhYTA3MCwgMHgzMmJiZDFiOCxcbiAgMHgxOWE0YzExNiwgMHhiOGQyZDBjOCwgMHgxZTM3NmMwOCwgMHg1MTQxYWI1MyxcbiAgMHgyNzQ4Nzc0YywgMHhkZjhlZWI5OSwgMHgzNGIwYmNiNSwgMHhlMTliNDhhOCxcbiAgMHgzOTFjMGNiMywgMHhjNWM5NWE2MywgMHg0ZWQ4YWE0YSwgMHhlMzQxOGFjYixcbiAgMHg1YjljY2E0ZiwgMHg3NzYzZTM3MywgMHg2ODJlNmZmMywgMHhkNmIyYjhhMyxcbiAgMHg3NDhmODJlZSwgMHg1ZGVmYjJmYywgMHg3OGE1NjM2ZiwgMHg0MzE3MmY2MCxcbiAgMHg4NGM4NzgxNCwgMHhhMWYwYWI3MiwgMHg4Y2M3MDIwOCwgMHgxYTY0MzllYyxcbiAgMHg5MGJlZmZmYSwgMHgyMzYzMWUyOCwgMHhhNDUwNmNlYiwgMHhkZTgyYmRlOSxcbiAgMHhiZWY5YTNmNywgMHhiMmM2NzkxNSwgMHhjNjcxNzhmMiwgMHhlMzcyNTMyYixcbiAgMHhjYTI3M2VjZSwgMHhlYTI2NjE5YywgMHhkMTg2YjhjNywgMHgyMWMwYzIwNyxcbiAgMHhlYWRhN2RkNiwgMHhjZGUwZWIxZSwgMHhmNTdkNGY3ZiwgMHhlZTZlZDE3OCxcbiAgMHgwNmYwNjdhYSwgMHg3MjE3NmZiYSwgMHgwYTYzN2RjNSwgMHhhMmM4OThhNixcbiAgMHgxMTNmOTgwNCwgMHhiZWY5MGRhZSwgMHgxYjcxMGIzNSwgMHgxMzFjNDcxYixcbiAgMHgyOGRiNzdmNSwgMHgyMzA0N2Q4NCwgMHgzMmNhYWI3YiwgMHg0MGM3MjQ5MyxcbiAgMHgzYzllYmUwYSwgMHgxNWM5YmViYywgMHg0MzFkNjdjNCwgMHg5YzEwMGQ0YyxcbiAgMHg0Y2M1ZDRiZSwgMHhjYjNlNDJiNiwgMHg1OTdmMjk5YywgMHhmYzY1N2UyYSxcbiAgMHg1ZmNiNmZhYiwgMHgzYWQ2ZmFlYywgMHg2YzQ0MTk4YywgMHg0YTQ3NTgxN1xuXVxuXG52YXIgVyA9IG5ldyBBcnJheSgxNjApXG5cbmZ1bmN0aW9uIFNoYTUxMiAoKSB7XG4gIHRoaXMuaW5pdCgpXG4gIHRoaXMuX3cgPSBXXG5cbiAgSGFzaC5jYWxsKHRoaXMsIDEyOCwgMTEyKVxufVxuXG5pbmhlcml0cyhTaGE1MTIsIEhhc2gpXG5cblNoYTUxMi5wcm90b3R5cGUuaW5pdCA9IGZ1bmN0aW9uICgpIHtcbiAgdGhpcy5fYWggPSAweDZhMDllNjY3XG4gIHRoaXMuX2JoID0gMHhiYjY3YWU4NVxuICB0aGlzLl9jaCA9IDB4M2M2ZWYzNzJcbiAgdGhpcy5fZGggPSAweGE1NGZmNTNhXG4gIHRoaXMuX2VoID0gMHg1MTBlNTI3ZlxuICB0aGlzLl9maCA9IDB4OWIwNTY4OGNcbiAgdGhpcy5fZ2ggPSAweDFmODNkOWFiXG4gIHRoaXMuX2hoID0gMHg1YmUwY2QxOVxuXG4gIHRoaXMuX2FsID0gMHhmM2JjYzkwOFxuICB0aGlzLl9ibCA9IDB4ODRjYWE3M2JcbiAgdGhpcy5fY2wgPSAweGZlOTRmODJiXG4gIHRoaXMuX2RsID0gMHg1ZjFkMzZmMVxuICB0aGlzLl9lbCA9IDB4YWRlNjgyZDFcbiAgdGhpcy5fZmwgPSAweDJiM2U2YzFmXG4gIHRoaXMuX2dsID0gMHhmYjQxYmQ2YlxuICB0aGlzLl9obCA9IDB4MTM3ZTIxNzlcblxuICByZXR1cm4gdGhpc1xufVxuXG5mdW5jdGlvbiBDaCAoeCwgeSwgeikge1xuICByZXR1cm4geiBeICh4ICYgKHkgXiB6KSlcbn1cblxuZnVuY3Rpb24gbWFqICh4LCB5LCB6KSB7XG4gIHJldHVybiAoeCAmIHkpIHwgKHogJiAoeCB8IHkpKVxufVxuXG5mdW5jdGlvbiBzaWdtYTAgKHgsIHhsKSB7XG4gIHJldHVybiAoeCA+Pj4gMjggfCB4bCA8PCA0KSBeICh4bCA+Pj4gMiB8IHggPDwgMzApIF4gKHhsID4+PiA3IHwgeCA8PCAyNSlcbn1cblxuZnVuY3Rpb24gc2lnbWExICh4LCB4bCkge1xuICByZXR1cm4gKHggPj4+IDE0IHwgeGwgPDwgMTgpIF4gKHggPj4+IDE4IHwgeGwgPDwgMTQpIF4gKHhsID4+PiA5IHwgeCA8PCAyMylcbn1cblxuZnVuY3Rpb24gR2FtbWEwICh4LCB4bCkge1xuICByZXR1cm4gKHggPj4+IDEgfCB4bCA8PCAzMSkgXiAoeCA+Pj4gOCB8IHhsIDw8IDI0KSBeICh4ID4+PiA3KVxufVxuXG5mdW5jdGlvbiBHYW1tYTBsICh4LCB4bCkge1xuICByZXR1cm4gKHggPj4+IDEgfCB4bCA8PCAzMSkgXiAoeCA+Pj4gOCB8IHhsIDw8IDI0KSBeICh4ID4+PiA3IHwgeGwgPDwgMjUpXG59XG5cbmZ1bmN0aW9uIEdhbW1hMSAoeCwgeGwpIHtcbiAgcmV0dXJuICh4ID4+PiAxOSB8IHhsIDw8IDEzKSBeICh4bCA+Pj4gMjkgfCB4IDw8IDMpIF4gKHggPj4+IDYpXG59XG5cbmZ1bmN0aW9uIEdhbW1hMWwgKHgsIHhsKSB7XG4gIHJldHVybiAoeCA+Pj4gMTkgfCB4bCA8PCAxMykgXiAoeGwgPj4+IDI5IHwgeCA8PCAzKSBeICh4ID4+PiA2IHwgeGwgPDwgMjYpXG59XG5cbmZ1bmN0aW9uIGdldENhcnJ5IChhLCBiKSB7XG4gIHJldHVybiAoYSA+Pj4gMCkgPCAoYiA+Pj4gMCkgPyAxIDogMFxufVxuXG5TaGE1MTIucHJvdG90eXBlLl91cGRhdGUgPSBmdW5jdGlvbiAoTSkge1xuICB2YXIgVyA9IHRoaXMuX3dcblxuICB2YXIgYWggPSB0aGlzLl9haCB8IDBcbiAgdmFyIGJoID0gdGhpcy5fYmggfCAwXG4gIHZhciBjaCA9IHRoaXMuX2NoIHwgMFxuICB2YXIgZGggPSB0aGlzLl9kaCB8IDBcbiAgdmFyIGVoID0gdGhpcy5fZWggfCAwXG4gIHZhciBmaCA9IHRoaXMuX2ZoIHwgMFxuICB2YXIgZ2ggPSB0aGlzLl9naCB8IDBcbiAgdmFyIGhoID0gdGhpcy5faGggfCAwXG5cbiAgdmFyIGFsID0gdGhpcy5fYWwgfCAwXG4gIHZhciBibCA9IHRoaXMuX2JsIHwgMFxuICB2YXIgY2wgPSB0aGlzLl9jbCB8IDBcbiAgdmFyIGRsID0gdGhpcy5fZGwgfCAwXG4gIHZhciBlbCA9IHRoaXMuX2VsIHwgMFxuICB2YXIgZmwgPSB0aGlzLl9mbCB8IDBcbiAgdmFyIGdsID0gdGhpcy5fZ2wgfCAwXG4gIHZhciBobCA9IHRoaXMuX2hsIHwgMFxuXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgMzI7IGkgKz0gMikge1xuICAgIFdbaV0gPSBNLnJlYWRJbnQzMkJFKGkgKiA0KVxuICAgIFdbaSArIDFdID0gTS5yZWFkSW50MzJCRShpICogNCArIDQpXG4gIH1cbiAgZm9yICg7IGkgPCAxNjA7IGkgKz0gMikge1xuICAgIHZhciB4aCA9IFdbaSAtIDE1ICogMl1cbiAgICB2YXIgeGwgPSBXW2kgLSAxNSAqIDIgKyAxXVxuICAgIHZhciBnYW1tYTAgPSBHYW1tYTAoeGgsIHhsKVxuICAgIHZhciBnYW1tYTBsID0gR2FtbWEwbCh4bCwgeGgpXG5cbiAgICB4aCA9IFdbaSAtIDIgKiAyXVxuICAgIHhsID0gV1tpIC0gMiAqIDIgKyAxXVxuICAgIHZhciBnYW1tYTEgPSBHYW1tYTEoeGgsIHhsKVxuICAgIHZhciBnYW1tYTFsID0gR2FtbWExbCh4bCwgeGgpXG5cbiAgICAvLyBXW2ldID0gZ2FtbWEwICsgV1tpIC0gN10gKyBnYW1tYTEgKyBXW2kgLSAxNl1cbiAgICB2YXIgV2k3aCA9IFdbaSAtIDcgKiAyXVxuICAgIHZhciBXaTdsID0gV1tpIC0gNyAqIDIgKyAxXVxuXG4gICAgdmFyIFdpMTZoID0gV1tpIC0gMTYgKiAyXVxuICAgIHZhciBXaTE2bCA9IFdbaSAtIDE2ICogMiArIDFdXG5cbiAgICB2YXIgV2lsID0gKGdhbW1hMGwgKyBXaTdsKSB8IDBcbiAgICB2YXIgV2loID0gKGdhbW1hMCArIFdpN2ggKyBnZXRDYXJyeShXaWwsIGdhbW1hMGwpKSB8IDBcbiAgICBXaWwgPSAoV2lsICsgZ2FtbWExbCkgfCAwXG4gICAgV2loID0gKFdpaCArIGdhbW1hMSArIGdldENhcnJ5KFdpbCwgZ2FtbWExbCkpIHwgMFxuICAgIFdpbCA9IChXaWwgKyBXaTE2bCkgfCAwXG4gICAgV2loID0gKFdpaCArIFdpMTZoICsgZ2V0Q2FycnkoV2lsLCBXaTE2bCkpIHwgMFxuXG4gICAgV1tpXSA9IFdpaFxuICAgIFdbaSArIDFdID0gV2lsXG4gIH1cblxuICBmb3IgKHZhciBqID0gMDsgaiA8IDE2MDsgaiArPSAyKSB7XG4gICAgV2loID0gV1tqXVxuICAgIFdpbCA9IFdbaiArIDFdXG5cbiAgICB2YXIgbWFqaCA9IG1haihhaCwgYmgsIGNoKVxuICAgIHZhciBtYWpsID0gbWFqKGFsLCBibCwgY2wpXG5cbiAgICB2YXIgc2lnbWEwaCA9IHNpZ21hMChhaCwgYWwpXG4gICAgdmFyIHNpZ21hMGwgPSBzaWdtYTAoYWwsIGFoKVxuICAgIHZhciBzaWdtYTFoID0gc2lnbWExKGVoLCBlbClcbiAgICB2YXIgc2lnbWExbCA9IHNpZ21hMShlbCwgZWgpXG5cbiAgICAvLyB0MSA9IGggKyBzaWdtYTEgKyBjaCArIEtbal0gKyBXW2pdXG4gICAgdmFyIEtpaCA9IEtbal1cbiAgICB2YXIgS2lsID0gS1tqICsgMV1cblxuICAgIHZhciBjaGggPSBDaChlaCwgZmgsIGdoKVxuICAgIHZhciBjaGwgPSBDaChlbCwgZmwsIGdsKVxuXG4gICAgdmFyIHQxbCA9IChobCArIHNpZ21hMWwpIHwgMFxuICAgIHZhciB0MWggPSAoaGggKyBzaWdtYTFoICsgZ2V0Q2FycnkodDFsLCBobCkpIHwgMFxuICAgIHQxbCA9ICh0MWwgKyBjaGwpIHwgMFxuICAgIHQxaCA9ICh0MWggKyBjaGggKyBnZXRDYXJyeSh0MWwsIGNobCkpIHwgMFxuICAgIHQxbCA9ICh0MWwgKyBLaWwpIHwgMFxuICAgIHQxaCA9ICh0MWggKyBLaWggKyBnZXRDYXJyeSh0MWwsIEtpbCkpIHwgMFxuICAgIHQxbCA9ICh0MWwgKyBXaWwpIHwgMFxuICAgIHQxaCA9ICh0MWggKyBXaWggKyBnZXRDYXJyeSh0MWwsIFdpbCkpIHwgMFxuXG4gICAgLy8gdDIgPSBzaWdtYTAgKyBtYWpcbiAgICB2YXIgdDJsID0gKHNpZ21hMGwgKyBtYWpsKSB8IDBcbiAgICB2YXIgdDJoID0gKHNpZ21hMGggKyBtYWpoICsgZ2V0Q2FycnkodDJsLCBzaWdtYTBsKSkgfCAwXG5cbiAgICBoaCA9IGdoXG4gICAgaGwgPSBnbFxuICAgIGdoID0gZmhcbiAgICBnbCA9IGZsXG4gICAgZmggPSBlaFxuICAgIGZsID0gZWxcbiAgICBlbCA9IChkbCArIHQxbCkgfCAwXG4gICAgZWggPSAoZGggKyB0MWggKyBnZXRDYXJyeShlbCwgZGwpKSB8IDBcbiAgICBkaCA9IGNoXG4gICAgZGwgPSBjbFxuICAgIGNoID0gYmhcbiAgICBjbCA9IGJsXG4gICAgYmggPSBhaFxuICAgIGJsID0gYWxcbiAgICBhbCA9ICh0MWwgKyB0MmwpIHwgMFxuICAgIGFoID0gKHQxaCArIHQyaCArIGdldENhcnJ5KGFsLCB0MWwpKSB8IDBcbiAgfVxuXG4gIHRoaXMuX2FsID0gKHRoaXMuX2FsICsgYWwpIHwgMFxuICB0aGlzLl9ibCA9ICh0aGlzLl9ibCArIGJsKSB8IDBcbiAgdGhpcy5fY2wgPSAodGhpcy5fY2wgKyBjbCkgfCAwXG4gIHRoaXMuX2RsID0gKHRoaXMuX2RsICsgZGwpIHwgMFxuICB0aGlzLl9lbCA9ICh0aGlzLl9lbCArIGVsKSB8IDBcbiAgdGhpcy5fZmwgPSAodGhpcy5fZmwgKyBmbCkgfCAwXG4gIHRoaXMuX2dsID0gKHRoaXMuX2dsICsgZ2wpIHwgMFxuICB0aGlzLl9obCA9ICh0aGlzLl9obCArIGhsKSB8IDBcblxuICB0aGlzLl9haCA9ICh0aGlzLl9haCArIGFoICsgZ2V0Q2FycnkodGhpcy5fYWwsIGFsKSkgfCAwXG4gIHRoaXMuX2JoID0gKHRoaXMuX2JoICsgYmggKyBnZXRDYXJyeSh0aGlzLl9ibCwgYmwpKSB8IDBcbiAgdGhpcy5fY2ggPSAodGhpcy5fY2ggKyBjaCArIGdldENhcnJ5KHRoaXMuX2NsLCBjbCkpIHwgMFxuICB0aGlzLl9kaCA9ICh0aGlzLl9kaCArIGRoICsgZ2V0Q2FycnkodGhpcy5fZGwsIGRsKSkgfCAwXG4gIHRoaXMuX2VoID0gKHRoaXMuX2VoICsgZWggKyBnZXRDYXJyeSh0aGlzLl9lbCwgZWwpKSB8IDBcbiAgdGhpcy5fZmggPSAodGhpcy5fZmggKyBmaCArIGdldENhcnJ5KHRoaXMuX2ZsLCBmbCkpIHwgMFxuICB0aGlzLl9naCA9ICh0aGlzLl9naCArIGdoICsgZ2V0Q2FycnkodGhpcy5fZ2wsIGdsKSkgfCAwXG4gIHRoaXMuX2hoID0gKHRoaXMuX2hoICsgaGggKyBnZXRDYXJyeSh0aGlzLl9obCwgaGwpKSB8IDBcbn1cblxuU2hhNTEyLnByb3RvdHlwZS5faGFzaCA9IGZ1bmN0aW9uICgpIHtcbiAgdmFyIEggPSBCdWZmZXIuYWxsb2NVbnNhZmUoNjQpXG5cbiAgZnVuY3Rpb24gd3JpdGVJbnQ2NEJFIChoLCBsLCBvZmZzZXQpIHtcbiAgICBILndyaXRlSW50MzJCRShoLCBvZmZzZXQpXG4gICAgSC53cml0ZUludDMyQkUobCwgb2Zmc2V0ICsgNClcbiAgfVxuXG4gIHdyaXRlSW50NjRCRSh0aGlzLl9haCwgdGhpcy5fYWwsIDApXG4gIHdyaXRlSW50NjRCRSh0aGlzLl9iaCwgdGhpcy5fYmwsIDgpXG4gIHdyaXRlSW50NjRCRSh0aGlzLl9jaCwgdGhpcy5fY2wsIDE2KVxuICB3cml0ZUludDY0QkUodGhpcy5fZGgsIHRoaXMuX2RsLCAyNClcbiAgd3JpdGVJbnQ2NEJFKHRoaXMuX2VoLCB0aGlzLl9lbCwgMzIpXG4gIHdyaXRlSW50NjRCRSh0aGlzLl9maCwgdGhpcy5fZmwsIDQwKVxuICB3cml0ZUludDY0QkUodGhpcy5fZ2gsIHRoaXMuX2dsLCA0OClcbiAgd3JpdGVJbnQ2NEJFKHRoaXMuX2hoLCB0aGlzLl9obCwgNTYpXG5cbiAgcmV0dXJuIEhcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBTaGE1MTJcbiIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG5tb2R1bGUuZXhwb3J0cyA9IFN0cmVhbTtcblxudmFyIEVFID0gcmVxdWlyZSgnZXZlbnRzJykuRXZlbnRFbWl0dGVyO1xudmFyIGluaGVyaXRzID0gcmVxdWlyZSgnaW5oZXJpdHMnKTtcblxuaW5oZXJpdHMoU3RyZWFtLCBFRSk7XG5TdHJlYW0uUmVhZGFibGUgPSByZXF1aXJlKCdyZWFkYWJsZS1zdHJlYW0vcmVhZGFibGUuanMnKTtcblN0cmVhbS5Xcml0YWJsZSA9IHJlcXVpcmUoJ3JlYWRhYmxlLXN0cmVhbS93cml0YWJsZS5qcycpO1xuU3RyZWFtLkR1cGxleCA9IHJlcXVpcmUoJ3JlYWRhYmxlLXN0cmVhbS9kdXBsZXguanMnKTtcblN0cmVhbS5UcmFuc2Zvcm0gPSByZXF1aXJlKCdyZWFkYWJsZS1zdHJlYW0vdHJhbnNmb3JtLmpzJyk7XG5TdHJlYW0uUGFzc1Rocm91Z2ggPSByZXF1aXJlKCdyZWFkYWJsZS1zdHJlYW0vcGFzc3Rocm91Z2guanMnKTtcblxuLy8gQmFja3dhcmRzLWNvbXBhdCB3aXRoIG5vZGUgMC40LnhcblN0cmVhbS5TdHJlYW0gPSBTdHJlYW07XG5cblxuXG4vLyBvbGQtc3R5bGUgc3RyZWFtcy4gIE5vdGUgdGhhdCB0aGUgcGlwZSBtZXRob2QgKHRoZSBvbmx5IHJlbGV2YW50XG4vLyBwYXJ0IG9mIHRoaXMgY2xhc3MpIGlzIG92ZXJyaWRkZW4gaW4gdGhlIFJlYWRhYmxlIGNsYXNzLlxuXG5mdW5jdGlvbiBTdHJlYW0oKSB7XG4gIEVFLmNhbGwodGhpcyk7XG59XG5cblN0cmVhbS5wcm90b3R5cGUucGlwZSA9IGZ1bmN0aW9uKGRlc3QsIG9wdGlvbnMpIHtcbiAgdmFyIHNvdXJjZSA9IHRoaXM7XG5cbiAgZnVuY3Rpb24gb25kYXRhKGNodW5rKSB7XG4gICAgaWYgKGRlc3Qud3JpdGFibGUpIHtcbiAgICAgIGlmIChmYWxzZSA9PT0gZGVzdC53cml0ZShjaHVuaykgJiYgc291cmNlLnBhdXNlKSB7XG4gICAgICAgIHNvdXJjZS5wYXVzZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHNvdXJjZS5vbignZGF0YScsIG9uZGF0YSk7XG5cbiAgZnVuY3Rpb24gb25kcmFpbigpIHtcbiAgICBpZiAoc291cmNlLnJlYWRhYmxlICYmIHNvdXJjZS5yZXN1bWUpIHtcbiAgICAgIHNvdXJjZS5yZXN1bWUoKTtcbiAgICB9XG4gIH1cblxuICBkZXN0Lm9uKCdkcmFpbicsIG9uZHJhaW4pO1xuXG4gIC8vIElmIHRoZSAnZW5kJyBvcHRpb24gaXMgbm90IHN1cHBsaWVkLCBkZXN0LmVuZCgpIHdpbGwgYmUgY2FsbGVkIHdoZW5cbiAgLy8gc291cmNlIGdldHMgdGhlICdlbmQnIG9yICdjbG9zZScgZXZlbnRzLiAgT25seSBkZXN0LmVuZCgpIG9uY2UuXG4gIGlmICghZGVzdC5faXNTdGRpbyAmJiAoIW9wdGlvbnMgfHwgb3B0aW9ucy5lbmQgIT09IGZhbHNlKSkge1xuICAgIHNvdXJjZS5vbignZW5kJywgb25lbmQpO1xuICAgIHNvdXJjZS5vbignY2xvc2UnLCBvbmNsb3NlKTtcbiAgfVxuXG4gIHZhciBkaWRPbkVuZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBvbmVuZCgpIHtcbiAgICBpZiAoZGlkT25FbmQpIHJldHVybjtcbiAgICBkaWRPbkVuZCA9IHRydWU7XG5cbiAgICBkZXN0LmVuZCgpO1xuICB9XG5cblxuICBmdW5jdGlvbiBvbmNsb3NlKCkge1xuICAgIGlmIChkaWRPbkVuZCkgcmV0dXJuO1xuICAgIGRpZE9uRW5kID0gdHJ1ZTtcblxuICAgIGlmICh0eXBlb2YgZGVzdC5kZXN0cm95ID09PSAnZnVuY3Rpb24nKSBkZXN0LmRlc3Ryb3koKTtcbiAgfVxuXG4gIC8vIGRvbid0IGxlYXZlIGRhbmdsaW5nIHBpcGVzIHdoZW4gdGhlcmUgYXJlIGVycm9ycy5cbiAgZnVuY3Rpb24gb25lcnJvcihlcikge1xuICAgIGNsZWFudXAoKTtcbiAgICBpZiAoRUUubGlzdGVuZXJDb3VudCh0aGlzLCAnZXJyb3InKSA9PT0gMCkge1xuICAgICAgdGhyb3cgZXI7IC8vIFVuaGFuZGxlZCBzdHJlYW0gZXJyb3IgaW4gcGlwZS5cbiAgICB9XG4gIH1cblxuICBzb3VyY2Uub24oJ2Vycm9yJywgb25lcnJvcik7XG4gIGRlc3Qub24oJ2Vycm9yJywgb25lcnJvcik7XG5cbiAgLy8gcmVtb3ZlIGFsbCB0aGUgZXZlbnQgbGlzdGVuZXJzIHRoYXQgd2VyZSBhZGRlZC5cbiAgZnVuY3Rpb24gY2xlYW51cCgpIHtcbiAgICBzb3VyY2UucmVtb3ZlTGlzdGVuZXIoJ2RhdGEnLCBvbmRhdGEpO1xuICAgIGRlc3QucmVtb3ZlTGlzdGVuZXIoJ2RyYWluJywgb25kcmFpbik7XG5cbiAgICBzb3VyY2UucmVtb3ZlTGlzdGVuZXIoJ2VuZCcsIG9uZW5kKTtcbiAgICBzb3VyY2UucmVtb3ZlTGlzdGVuZXIoJ2Nsb3NlJywgb25jbG9zZSk7XG5cbiAgICBzb3VyY2UucmVtb3ZlTGlzdGVuZXIoJ2Vycm9yJywgb25lcnJvcik7XG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignZXJyb3InLCBvbmVycm9yKTtcblxuICAgIHNvdXJjZS5yZW1vdmVMaXN0ZW5lcignZW5kJywgY2xlYW51cCk7XG4gICAgc291cmNlLnJlbW92ZUxpc3RlbmVyKCdjbG9zZScsIGNsZWFudXApO1xuXG4gICAgZGVzdC5yZW1vdmVMaXN0ZW5lcignY2xvc2UnLCBjbGVhbnVwKTtcbiAgfVxuXG4gIHNvdXJjZS5vbignZW5kJywgY2xlYW51cCk7XG4gIHNvdXJjZS5vbignY2xvc2UnLCBjbGVhbnVwKTtcblxuICBkZXN0Lm9uKCdjbG9zZScsIGNsZWFudXApO1xuXG4gIGRlc3QuZW1pdCgncGlwZScsIHNvdXJjZSk7XG5cbiAgLy8gQWxsb3cgZm9yIHVuaXgtbGlrZSB1c2FnZTogQS5waXBlKEIpLnBpcGUoQylcbiAgcmV0dXJuIGRlc3Q7XG59O1xuIiwiLy8gQ29weXJpZ2h0IEpveWVudCwgSW5jLiBhbmQgb3RoZXIgTm9kZSBjb250cmlidXRvcnMuXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGFcbi8vIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGVcbi8vIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZ1xuLy8gd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLFxuLy8gZGlzdHJpYnV0ZSwgc3VibGljZW5zZSwgYW5kL29yIHNlbGwgY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdFxuLy8gcGVyc29ucyB0byB3aG9tIHRoZSBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlXG4vLyBmb2xsb3dpbmcgY29uZGl0aW9uczpcbi8vXG4vLyBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZFxuLy8gaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCwgRVhQUkVTU1xuLy8gT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFUyBPRlxuLy8gTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkQgTk9OSU5GUklOR0VNRU5ULiBJTlxuLy8gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sXG4vLyBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1Jcbi8vIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEVcbi8vIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbid1c2Ugc3RyaWN0JztcblxuLyo8cmVwbGFjZW1lbnQ+Ki9cblxudmFyIEJ1ZmZlciA9IHJlcXVpcmUoJ3NhZmUtYnVmZmVyJykuQnVmZmVyO1xuLyo8L3JlcGxhY2VtZW50PiovXG5cbnZhciBpc0VuY29kaW5nID0gQnVmZmVyLmlzRW5jb2RpbmcgfHwgZnVuY3Rpb24gKGVuY29kaW5nKSB7XG4gIGVuY29kaW5nID0gJycgKyBlbmNvZGluZztcbiAgc3dpdGNoIChlbmNvZGluZyAmJiBlbmNvZGluZy50b0xvd2VyQ2FzZSgpKSB7XG4gICAgY2FzZSAnaGV4JzpjYXNlICd1dGY4JzpjYXNlICd1dGYtOCc6Y2FzZSAnYXNjaWknOmNhc2UgJ2JpbmFyeSc6Y2FzZSAnYmFzZTY0JzpjYXNlICd1Y3MyJzpjYXNlICd1Y3MtMic6Y2FzZSAndXRmMTZsZSc6Y2FzZSAndXRmLTE2bGUnOmNhc2UgJ3Jhdyc6XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICBkZWZhdWx0OlxuICAgICAgcmV0dXJuIGZhbHNlO1xuICB9XG59O1xuXG5mdW5jdGlvbiBfbm9ybWFsaXplRW5jb2RpbmcoZW5jKSB7XG4gIGlmICghZW5jKSByZXR1cm4gJ3V0ZjgnO1xuICB2YXIgcmV0cmllZDtcbiAgd2hpbGUgKHRydWUpIHtcbiAgICBzd2l0Y2ggKGVuYykge1xuICAgICAgY2FzZSAndXRmOCc6XG4gICAgICBjYXNlICd1dGYtOCc6XG4gICAgICAgIHJldHVybiAndXRmOCc7XG4gICAgICBjYXNlICd1Y3MyJzpcbiAgICAgIGNhc2UgJ3Vjcy0yJzpcbiAgICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgY2FzZSAndXRmLTE2bGUnOlxuICAgICAgICByZXR1cm4gJ3V0ZjE2bGUnO1xuICAgICAgY2FzZSAnbGF0aW4xJzpcbiAgICAgIGNhc2UgJ2JpbmFyeSc6XG4gICAgICAgIHJldHVybiAnbGF0aW4xJztcbiAgICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICBjYXNlICdhc2NpaSc6XG4gICAgICBjYXNlICdoZXgnOlxuICAgICAgICByZXR1cm4gZW5jO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgaWYgKHJldHJpZWQpIHJldHVybjsgLy8gdW5kZWZpbmVkXG4gICAgICAgIGVuYyA9ICgnJyArIGVuYykudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0cmllZCA9IHRydWU7XG4gICAgfVxuICB9XG59O1xuXG4vLyBEbyBub3QgY2FjaGUgYEJ1ZmZlci5pc0VuY29kaW5nYCB3aGVuIGNoZWNraW5nIGVuY29kaW5nIG5hbWVzIGFzIHNvbWVcbi8vIG1vZHVsZXMgbW9ua2V5LXBhdGNoIGl0IHRvIHN1cHBvcnQgYWRkaXRpb25hbCBlbmNvZGluZ3NcbmZ1bmN0aW9uIG5vcm1hbGl6ZUVuY29kaW5nKGVuYykge1xuICB2YXIgbmVuYyA9IF9ub3JtYWxpemVFbmNvZGluZyhlbmMpO1xuICBpZiAodHlwZW9mIG5lbmMgIT09ICdzdHJpbmcnICYmIChCdWZmZXIuaXNFbmNvZGluZyA9PT0gaXNFbmNvZGluZyB8fCAhaXNFbmNvZGluZyhlbmMpKSkgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIGVuY29kaW5nOiAnICsgZW5jKTtcbiAgcmV0dXJuIG5lbmMgfHwgZW5jO1xufVxuXG4vLyBTdHJpbmdEZWNvZGVyIHByb3ZpZGVzIGFuIGludGVyZmFjZSBmb3IgZWZmaWNpZW50bHkgc3BsaXR0aW5nIGEgc2VyaWVzIG9mXG4vLyBidWZmZXJzIGludG8gYSBzZXJpZXMgb2YgSlMgc3RyaW5ncyB3aXRob3V0IGJyZWFraW5nIGFwYXJ0IG11bHRpLWJ5dGVcbi8vIGNoYXJhY3RlcnMuXG5leHBvcnRzLlN0cmluZ0RlY29kZXIgPSBTdHJpbmdEZWNvZGVyO1xuZnVuY3Rpb24gU3RyaW5nRGVjb2RlcihlbmNvZGluZykge1xuICB0aGlzLmVuY29kaW5nID0gbm9ybWFsaXplRW5jb2RpbmcoZW5jb2RpbmcpO1xuICB2YXIgbmI7XG4gIHN3aXRjaCAodGhpcy5lbmNvZGluZykge1xuICAgIGNhc2UgJ3V0ZjE2bGUnOlxuICAgICAgdGhpcy50ZXh0ID0gdXRmMTZUZXh0O1xuICAgICAgdGhpcy5lbmQgPSB1dGYxNkVuZDtcbiAgICAgIG5iID0gNDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ3V0ZjgnOlxuICAgICAgdGhpcy5maWxsTGFzdCA9IHV0ZjhGaWxsTGFzdDtcbiAgICAgIG5iID0gNDtcbiAgICAgIGJyZWFrO1xuICAgIGNhc2UgJ2Jhc2U2NCc6XG4gICAgICB0aGlzLnRleHQgPSBiYXNlNjRUZXh0O1xuICAgICAgdGhpcy5lbmQgPSBiYXNlNjRFbmQ7XG4gICAgICBuYiA9IDM7XG4gICAgICBicmVhaztcbiAgICBkZWZhdWx0OlxuICAgICAgdGhpcy53cml0ZSA9IHNpbXBsZVdyaXRlO1xuICAgICAgdGhpcy5lbmQgPSBzaW1wbGVFbmQ7XG4gICAgICByZXR1cm47XG4gIH1cbiAgdGhpcy5sYXN0TmVlZCA9IDA7XG4gIHRoaXMubGFzdFRvdGFsID0gMDtcbiAgdGhpcy5sYXN0Q2hhciA9IEJ1ZmZlci5hbGxvY1Vuc2FmZShuYik7XG59XG5cblN0cmluZ0RlY29kZXIucHJvdG90eXBlLndyaXRlID0gZnVuY3Rpb24gKGJ1Zikge1xuICBpZiAoYnVmLmxlbmd0aCA9PT0gMCkgcmV0dXJuICcnO1xuICB2YXIgcjtcbiAgdmFyIGk7XG4gIGlmICh0aGlzLmxhc3ROZWVkKSB7XG4gICAgciA9IHRoaXMuZmlsbExhc3QoYnVmKTtcbiAgICBpZiAociA9PT0gdW5kZWZpbmVkKSByZXR1cm4gJyc7XG4gICAgaSA9IHRoaXMubGFzdE5lZWQ7XG4gICAgdGhpcy5sYXN0TmVlZCA9IDA7XG4gIH0gZWxzZSB7XG4gICAgaSA9IDA7XG4gIH1cbiAgaWYgKGkgPCBidWYubGVuZ3RoKSByZXR1cm4gciA/IHIgKyB0aGlzLnRleHQoYnVmLCBpKSA6IHRoaXMudGV4dChidWYsIGkpO1xuICByZXR1cm4gciB8fCAnJztcbn07XG5cblN0cmluZ0RlY29kZXIucHJvdG90eXBlLmVuZCA9IHV0ZjhFbmQ7XG5cbi8vIFJldHVybnMgb25seSBjb21wbGV0ZSBjaGFyYWN0ZXJzIGluIGEgQnVmZmVyXG5TdHJpbmdEZWNvZGVyLnByb3RvdHlwZS50ZXh0ID0gdXRmOFRleHQ7XG5cbi8vIEF0dGVtcHRzIHRvIGNvbXBsZXRlIGEgcGFydGlhbCBub24tVVRGLTggY2hhcmFjdGVyIHVzaW5nIGJ5dGVzIGZyb20gYSBCdWZmZXJcblN0cmluZ0RlY29kZXIucHJvdG90eXBlLmZpbGxMYXN0ID0gZnVuY3Rpb24gKGJ1Zikge1xuICBpZiAodGhpcy5sYXN0TmVlZCA8PSBidWYubGVuZ3RoKSB7XG4gICAgYnVmLmNvcHkodGhpcy5sYXN0Q2hhciwgdGhpcy5sYXN0VG90YWwgLSB0aGlzLmxhc3ROZWVkLCAwLCB0aGlzLmxhc3ROZWVkKTtcbiAgICByZXR1cm4gdGhpcy5sYXN0Q2hhci50b1N0cmluZyh0aGlzLmVuY29kaW5nLCAwLCB0aGlzLmxhc3RUb3RhbCk7XG4gIH1cbiAgYnVmLmNvcHkodGhpcy5sYXN0Q2hhciwgdGhpcy5sYXN0VG90YWwgLSB0aGlzLmxhc3ROZWVkLCAwLCBidWYubGVuZ3RoKTtcbiAgdGhpcy5sYXN0TmVlZCAtPSBidWYubGVuZ3RoO1xufTtcblxuLy8gQ2hlY2tzIHRoZSB0eXBlIG9mIGEgVVRGLTggYnl0ZSwgd2hldGhlciBpdCdzIEFTQ0lJLCBhIGxlYWRpbmcgYnl0ZSwgb3IgYVxuLy8gY29udGludWF0aW9uIGJ5dGUuIElmIGFuIGludmFsaWQgYnl0ZSBpcyBkZXRlY3RlZCwgLTIgaXMgcmV0dXJuZWQuXG5mdW5jdGlvbiB1dGY4Q2hlY2tCeXRlKGJ5dGUpIHtcbiAgaWYgKGJ5dGUgPD0gMHg3RikgcmV0dXJuIDA7ZWxzZSBpZiAoYnl0ZSA+PiA1ID09PSAweDA2KSByZXR1cm4gMjtlbHNlIGlmIChieXRlID4+IDQgPT09IDB4MEUpIHJldHVybiAzO2Vsc2UgaWYgKGJ5dGUgPj4gMyA9PT0gMHgxRSkgcmV0dXJuIDQ7XG4gIHJldHVybiBieXRlID4+IDYgPT09IDB4MDIgPyAtMSA6IC0yO1xufVxuXG4vLyBDaGVja3MgYXQgbW9zdCAzIGJ5dGVzIGF0IHRoZSBlbmQgb2YgYSBCdWZmZXIgaW4gb3JkZXIgdG8gZGV0ZWN0IGFuXG4vLyBpbmNvbXBsZXRlIG11bHRpLWJ5dGUgVVRGLTggY2hhcmFjdGVyLiBUaGUgdG90YWwgbnVtYmVyIG9mIGJ5dGVzICgyLCAzLCBvciA0KVxuLy8gbmVlZGVkIHRvIGNvbXBsZXRlIHRoZSBVVEYtOCBjaGFyYWN0ZXIgKGlmIGFwcGxpY2FibGUpIGFyZSByZXR1cm5lZC5cbmZ1bmN0aW9uIHV0ZjhDaGVja0luY29tcGxldGUoc2VsZiwgYnVmLCBpKSB7XG4gIHZhciBqID0gYnVmLmxlbmd0aCAtIDE7XG4gIGlmIChqIDwgaSkgcmV0dXJuIDA7XG4gIHZhciBuYiA9IHV0ZjhDaGVja0J5dGUoYnVmW2pdKTtcbiAgaWYgKG5iID49IDApIHtcbiAgICBpZiAobmIgPiAwKSBzZWxmLmxhc3ROZWVkID0gbmIgLSAxO1xuICAgIHJldHVybiBuYjtcbiAgfVxuICBpZiAoLS1qIDwgaSB8fCBuYiA9PT0gLTIpIHJldHVybiAwO1xuICBuYiA9IHV0ZjhDaGVja0J5dGUoYnVmW2pdKTtcbiAgaWYgKG5iID49IDApIHtcbiAgICBpZiAobmIgPiAwKSBzZWxmLmxhc3ROZWVkID0gbmIgLSAyO1xuICAgIHJldHVybiBuYjtcbiAgfVxuICBpZiAoLS1qIDwgaSB8fCBuYiA9PT0gLTIpIHJldHVybiAwO1xuICBuYiA9IHV0ZjhDaGVja0J5dGUoYnVmW2pdKTtcbiAgaWYgKG5iID49IDApIHtcbiAgICBpZiAobmIgPiAwKSB7XG4gICAgICBpZiAobmIgPT09IDIpIG5iID0gMDtlbHNlIHNlbGYubGFzdE5lZWQgPSBuYiAtIDM7XG4gICAgfVxuICAgIHJldHVybiBuYjtcbiAgfVxuICByZXR1cm4gMDtcbn1cblxuLy8gVmFsaWRhdGVzIGFzIG1hbnkgY29udGludWF0aW9uIGJ5dGVzIGZvciBhIG11bHRpLWJ5dGUgVVRGLTggY2hhcmFjdGVyIGFzXG4vLyBuZWVkZWQgb3IgYXJlIGF2YWlsYWJsZS4gSWYgd2Ugc2VlIGEgbm9uLWNvbnRpbnVhdGlvbiBieXRlIHdoZXJlIHdlIGV4cGVjdFxuLy8gb25lLCB3ZSBcInJlcGxhY2VcIiB0aGUgdmFsaWRhdGVkIGNvbnRpbnVhdGlvbiBieXRlcyB3ZSd2ZSBzZWVuIHNvIGZhciB3aXRoXG4vLyBhIHNpbmdsZSBVVEYtOCByZXBsYWNlbWVudCBjaGFyYWN0ZXIgKCdcXHVmZmZkJyksIHRvIG1hdGNoIHY4J3MgVVRGLTggZGVjb2Rpbmdcbi8vIGJlaGF2aW9yLiBUaGUgY29udGludWF0aW9uIGJ5dGUgY2hlY2sgaXMgaW5jbHVkZWQgdGhyZWUgdGltZXMgaW4gdGhlIGNhc2Vcbi8vIHdoZXJlIGFsbCBvZiB0aGUgY29udGludWF0aW9uIGJ5dGVzIGZvciBhIGNoYXJhY3RlciBleGlzdCBpbiB0aGUgc2FtZSBidWZmZXIuXG4vLyBJdCBpcyBhbHNvIGRvbmUgdGhpcyB3YXkgYXMgYSBzbGlnaHQgcGVyZm9ybWFuY2UgaW5jcmVhc2UgaW5zdGVhZCBvZiB1c2luZyBhXG4vLyBsb29wLlxuZnVuY3Rpb24gdXRmOENoZWNrRXh0cmFCeXRlcyhzZWxmLCBidWYsIHApIHtcbiAgaWYgKChidWZbMF0gJiAweEMwKSAhPT0gMHg4MCkge1xuICAgIHNlbGYubGFzdE5lZWQgPSAwO1xuICAgIHJldHVybiAnXFx1ZmZmZCc7XG4gIH1cbiAgaWYgKHNlbGYubGFzdE5lZWQgPiAxICYmIGJ1Zi5sZW5ndGggPiAxKSB7XG4gICAgaWYgKChidWZbMV0gJiAweEMwKSAhPT0gMHg4MCkge1xuICAgICAgc2VsZi5sYXN0TmVlZCA9IDE7XG4gICAgICByZXR1cm4gJ1xcdWZmZmQnO1xuICAgIH1cbiAgICBpZiAoc2VsZi5sYXN0TmVlZCA+IDIgJiYgYnVmLmxlbmd0aCA+IDIpIHtcbiAgICAgIGlmICgoYnVmWzJdICYgMHhDMCkgIT09IDB4ODApIHtcbiAgICAgICAgc2VsZi5sYXN0TmVlZCA9IDI7XG4gICAgICAgIHJldHVybiAnXFx1ZmZmZCc7XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbi8vIEF0dGVtcHRzIHRvIGNvbXBsZXRlIGEgbXVsdGktYnl0ZSBVVEYtOCBjaGFyYWN0ZXIgdXNpbmcgYnl0ZXMgZnJvbSBhIEJ1ZmZlci5cbmZ1bmN0aW9uIHV0ZjhGaWxsTGFzdChidWYpIHtcbiAgdmFyIHAgPSB0aGlzLmxhc3RUb3RhbCAtIHRoaXMubGFzdE5lZWQ7XG4gIHZhciByID0gdXRmOENoZWNrRXh0cmFCeXRlcyh0aGlzLCBidWYsIHApO1xuICBpZiAociAhPT0gdW5kZWZpbmVkKSByZXR1cm4gcjtcbiAgaWYgKHRoaXMubGFzdE5lZWQgPD0gYnVmLmxlbmd0aCkge1xuICAgIGJ1Zi5jb3B5KHRoaXMubGFzdENoYXIsIHAsIDAsIHRoaXMubGFzdE5lZWQpO1xuICAgIHJldHVybiB0aGlzLmxhc3RDaGFyLnRvU3RyaW5nKHRoaXMuZW5jb2RpbmcsIDAsIHRoaXMubGFzdFRvdGFsKTtcbiAgfVxuICBidWYuY29weSh0aGlzLmxhc3RDaGFyLCBwLCAwLCBidWYubGVuZ3RoKTtcbiAgdGhpcy5sYXN0TmVlZCAtPSBidWYubGVuZ3RoO1xufVxuXG4vLyBSZXR1cm5zIGFsbCBjb21wbGV0ZSBVVEYtOCBjaGFyYWN0ZXJzIGluIGEgQnVmZmVyLiBJZiB0aGUgQnVmZmVyIGVuZGVkIG9uIGFcbi8vIHBhcnRpYWwgY2hhcmFjdGVyLCB0aGUgY2hhcmFjdGVyJ3MgYnl0ZXMgYXJlIGJ1ZmZlcmVkIHVudGlsIHRoZSByZXF1aXJlZFxuLy8gbnVtYmVyIG9mIGJ5dGVzIGFyZSBhdmFpbGFibGUuXG5mdW5jdGlvbiB1dGY4VGV4dChidWYsIGkpIHtcbiAgdmFyIHRvdGFsID0gdXRmOENoZWNrSW5jb21wbGV0ZSh0aGlzLCBidWYsIGkpO1xuICBpZiAoIXRoaXMubGFzdE5lZWQpIHJldHVybiBidWYudG9TdHJpbmcoJ3V0ZjgnLCBpKTtcbiAgdGhpcy5sYXN0VG90YWwgPSB0b3RhbDtcbiAgdmFyIGVuZCA9IGJ1Zi5sZW5ndGggLSAodG90YWwgLSB0aGlzLmxhc3ROZWVkKTtcbiAgYnVmLmNvcHkodGhpcy5sYXN0Q2hhciwgMCwgZW5kKTtcbiAgcmV0dXJuIGJ1Zi50b1N0cmluZygndXRmOCcsIGksIGVuZCk7XG59XG5cbi8vIEZvciBVVEYtOCwgYSByZXBsYWNlbWVudCBjaGFyYWN0ZXIgaXMgYWRkZWQgd2hlbiBlbmRpbmcgb24gYSBwYXJ0aWFsXG4vLyBjaGFyYWN0ZXIuXG5mdW5jdGlvbiB1dGY4RW5kKGJ1Zikge1xuICB2YXIgciA9IGJ1ZiAmJiBidWYubGVuZ3RoID8gdGhpcy53cml0ZShidWYpIDogJyc7XG4gIGlmICh0aGlzLmxhc3ROZWVkKSByZXR1cm4gciArICdcXHVmZmZkJztcbiAgcmV0dXJuIHI7XG59XG5cbi8vIFVURi0xNkxFIHR5cGljYWxseSBuZWVkcyB0d28gYnl0ZXMgcGVyIGNoYXJhY3RlciwgYnV0IGV2ZW4gaWYgd2UgaGF2ZSBhbiBldmVuXG4vLyBudW1iZXIgb2YgYnl0ZXMgYXZhaWxhYmxlLCB3ZSBuZWVkIHRvIGNoZWNrIGlmIHdlIGVuZCBvbiBhIGxlYWRpbmcvaGlnaFxuLy8gc3Vycm9nYXRlLiBJbiB0aGF0IGNhc2UsIHdlIG5lZWQgdG8gd2FpdCBmb3IgdGhlIG5leHQgdHdvIGJ5dGVzIGluIG9yZGVyIHRvXG4vLyBkZWNvZGUgdGhlIGxhc3QgY2hhcmFjdGVyIHByb3Blcmx5LlxuZnVuY3Rpb24gdXRmMTZUZXh0KGJ1ZiwgaSkge1xuICBpZiAoKGJ1Zi5sZW5ndGggLSBpKSAlIDIgPT09IDApIHtcbiAgICB2YXIgciA9IGJ1Zi50b1N0cmluZygndXRmMTZsZScsIGkpO1xuICAgIGlmIChyKSB7XG4gICAgICB2YXIgYyA9IHIuY2hhckNvZGVBdChyLmxlbmd0aCAtIDEpO1xuICAgICAgaWYgKGMgPj0gMHhEODAwICYmIGMgPD0gMHhEQkZGKSB7XG4gICAgICAgIHRoaXMubGFzdE5lZWQgPSAyO1xuICAgICAgICB0aGlzLmxhc3RUb3RhbCA9IDQ7XG4gICAgICAgIHRoaXMubGFzdENoYXJbMF0gPSBidWZbYnVmLmxlbmd0aCAtIDJdO1xuICAgICAgICB0aGlzLmxhc3RDaGFyWzFdID0gYnVmW2J1Zi5sZW5ndGggLSAxXTtcbiAgICAgICAgcmV0dXJuIHIuc2xpY2UoMCwgLTEpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gcjtcbiAgfVxuICB0aGlzLmxhc3ROZWVkID0gMTtcbiAgdGhpcy5sYXN0VG90YWwgPSAyO1xuICB0aGlzLmxhc3RDaGFyWzBdID0gYnVmW2J1Zi5sZW5ndGggLSAxXTtcbiAgcmV0dXJuIGJ1Zi50b1N0cmluZygndXRmMTZsZScsIGksIGJ1Zi5sZW5ndGggLSAxKTtcbn1cblxuLy8gRm9yIFVURi0xNkxFIHdlIGRvIG5vdCBleHBsaWNpdGx5IGFwcGVuZCBzcGVjaWFsIHJlcGxhY2VtZW50IGNoYXJhY3RlcnMgaWYgd2Vcbi8vIGVuZCBvbiBhIHBhcnRpYWwgY2hhcmFjdGVyLCB3ZSBzaW1wbHkgbGV0IHY4IGhhbmRsZSB0aGF0LlxuZnVuY3Rpb24gdXRmMTZFbmQoYnVmKSB7XG4gIHZhciByID0gYnVmICYmIGJ1Zi5sZW5ndGggPyB0aGlzLndyaXRlKGJ1ZikgOiAnJztcbiAgaWYgKHRoaXMubGFzdE5lZWQpIHtcbiAgICB2YXIgZW5kID0gdGhpcy5sYXN0VG90YWwgLSB0aGlzLmxhc3ROZWVkO1xuICAgIHJldHVybiByICsgdGhpcy5sYXN0Q2hhci50b1N0cmluZygndXRmMTZsZScsIDAsIGVuZCk7XG4gIH1cbiAgcmV0dXJuIHI7XG59XG5cbmZ1bmN0aW9uIGJhc2U2NFRleHQoYnVmLCBpKSB7XG4gIHZhciBuID0gKGJ1Zi5sZW5ndGggLSBpKSAlIDM7XG4gIGlmIChuID09PSAwKSByZXR1cm4gYnVmLnRvU3RyaW5nKCdiYXNlNjQnLCBpKTtcbiAgdGhpcy5sYXN0TmVlZCA9IDMgLSBuO1xuICB0aGlzLmxhc3RUb3RhbCA9IDM7XG4gIGlmIChuID09PSAxKSB7XG4gICAgdGhpcy5sYXN0Q2hhclswXSA9IGJ1ZltidWYubGVuZ3RoIC0gMV07XG4gIH0gZWxzZSB7XG4gICAgdGhpcy5sYXN0Q2hhclswXSA9IGJ1ZltidWYubGVuZ3RoIC0gMl07XG4gICAgdGhpcy5sYXN0Q2hhclsxXSA9IGJ1ZltidWYubGVuZ3RoIC0gMV07XG4gIH1cbiAgcmV0dXJuIGJ1Zi50b1N0cmluZygnYmFzZTY0JywgaSwgYnVmLmxlbmd0aCAtIG4pO1xufVxuXG5mdW5jdGlvbiBiYXNlNjRFbmQoYnVmKSB7XG4gIHZhciByID0gYnVmICYmIGJ1Zi5sZW5ndGggPyB0aGlzLndyaXRlKGJ1ZikgOiAnJztcbiAgaWYgKHRoaXMubGFzdE5lZWQpIHJldHVybiByICsgdGhpcy5sYXN0Q2hhci50b1N0cmluZygnYmFzZTY0JywgMCwgMyAtIHRoaXMubGFzdE5lZWQpO1xuICByZXR1cm4gcjtcbn1cblxuLy8gUGFzcyBieXRlcyBvbiB0aHJvdWdoIGZvciBzaW5nbGUtYnl0ZSBlbmNvZGluZ3MgKGUuZy4gYXNjaWksIGxhdGluMSwgaGV4KVxuZnVuY3Rpb24gc2ltcGxlV3JpdGUoYnVmKSB7XG4gIHJldHVybiBidWYudG9TdHJpbmcodGhpcy5lbmNvZGluZyk7XG59XG5cbmZ1bmN0aW9uIHNpbXBsZUVuZChidWYpIHtcbiAgcmV0dXJuIGJ1ZiAmJiBidWYubGVuZ3RoID8gdGhpcy53cml0ZShidWYpIDogJyc7XG59IiwidmFyIG5leHRUaWNrID0gcmVxdWlyZSgncHJvY2Vzcy9icm93c2VyLmpzJykubmV4dFRpY2s7XG52YXIgYXBwbHkgPSBGdW5jdGlvbi5wcm90b3R5cGUuYXBwbHk7XG52YXIgc2xpY2UgPSBBcnJheS5wcm90b3R5cGUuc2xpY2U7XG52YXIgaW1tZWRpYXRlSWRzID0ge307XG52YXIgbmV4dEltbWVkaWF0ZUlkID0gMDtcblxuLy8gRE9NIEFQSXMsIGZvciBjb21wbGV0ZW5lc3NcblxuZXhwb3J0cy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgVGltZW91dChhcHBseS5jYWxsKHNldFRpbWVvdXQsIHdpbmRvdywgYXJndW1lbnRzKSwgY2xlYXJUaW1lb3V0KTtcbn07XG5leHBvcnRzLnNldEludGVydmFsID0gZnVuY3Rpb24oKSB7XG4gIHJldHVybiBuZXcgVGltZW91dChhcHBseS5jYWxsKHNldEludGVydmFsLCB3aW5kb3csIGFyZ3VtZW50cyksIGNsZWFySW50ZXJ2YWwpO1xufTtcbmV4cG9ydHMuY2xlYXJUaW1lb3V0ID1cbmV4cG9ydHMuY2xlYXJJbnRlcnZhbCA9IGZ1bmN0aW9uKHRpbWVvdXQpIHsgdGltZW91dC5jbG9zZSgpOyB9O1xuXG5mdW5jdGlvbiBUaW1lb3V0KGlkLCBjbGVhckZuKSB7XG4gIHRoaXMuX2lkID0gaWQ7XG4gIHRoaXMuX2NsZWFyRm4gPSBjbGVhckZuO1xufVxuVGltZW91dC5wcm90b3R5cGUudW5yZWYgPSBUaW1lb3V0LnByb3RvdHlwZS5yZWYgPSBmdW5jdGlvbigpIHt9O1xuVGltZW91dC5wcm90b3R5cGUuY2xvc2UgPSBmdW5jdGlvbigpIHtcbiAgdGhpcy5fY2xlYXJGbi5jYWxsKHdpbmRvdywgdGhpcy5faWQpO1xufTtcblxuLy8gRG9lcyBub3Qgc3RhcnQgdGhlIHRpbWUsIGp1c3Qgc2V0cyB1cCB0aGUgbWVtYmVycyBuZWVkZWQuXG5leHBvcnRzLmVucm9sbCA9IGZ1bmN0aW9uKGl0ZW0sIG1zZWNzKSB7XG4gIGNsZWFyVGltZW91dChpdGVtLl9pZGxlVGltZW91dElkKTtcbiAgaXRlbS5faWRsZVRpbWVvdXQgPSBtc2Vjcztcbn07XG5cbmV4cG9ydHMudW5lbnJvbGwgPSBmdW5jdGlvbihpdGVtKSB7XG4gIGNsZWFyVGltZW91dChpdGVtLl9pZGxlVGltZW91dElkKTtcbiAgaXRlbS5faWRsZVRpbWVvdXQgPSAtMTtcbn07XG5cbmV4cG9ydHMuX3VucmVmQWN0aXZlID0gZXhwb3J0cy5hY3RpdmUgPSBmdW5jdGlvbihpdGVtKSB7XG4gIGNsZWFyVGltZW91dChpdGVtLl9pZGxlVGltZW91dElkKTtcblxuICB2YXIgbXNlY3MgPSBpdGVtLl9pZGxlVGltZW91dDtcbiAgaWYgKG1zZWNzID49IDApIHtcbiAgICBpdGVtLl9pZGxlVGltZW91dElkID0gc2V0VGltZW91dChmdW5jdGlvbiBvblRpbWVvdXQoKSB7XG4gICAgICBpZiAoaXRlbS5fb25UaW1lb3V0KVxuICAgICAgICBpdGVtLl9vblRpbWVvdXQoKTtcbiAgICB9LCBtc2Vjcyk7XG4gIH1cbn07XG5cbi8vIFRoYXQncyBub3QgaG93IG5vZGUuanMgaW1wbGVtZW50cyBpdCBidXQgdGhlIGV4cG9zZWQgYXBpIGlzIHRoZSBzYW1lLlxuZXhwb3J0cy5zZXRJbW1lZGlhdGUgPSB0eXBlb2Ygc2V0SW1tZWRpYXRlID09PSBcImZ1bmN0aW9uXCIgPyBzZXRJbW1lZGlhdGUgOiBmdW5jdGlvbihmbikge1xuICB2YXIgaWQgPSBuZXh0SW1tZWRpYXRlSWQrKztcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHMubGVuZ3RoIDwgMiA/IGZhbHNlIDogc2xpY2UuY2FsbChhcmd1bWVudHMsIDEpO1xuXG4gIGltbWVkaWF0ZUlkc1tpZF0gPSB0cnVlO1xuXG4gIG5leHRUaWNrKGZ1bmN0aW9uIG9uTmV4dFRpY2soKSB7XG4gICAgaWYgKGltbWVkaWF0ZUlkc1tpZF0pIHtcbiAgICAgIC8vIGZuLmNhbGwoKSBpcyBmYXN0ZXIgc28gd2Ugb3B0aW1pemUgZm9yIHRoZSBjb21tb24gdXNlLWNhc2VcbiAgICAgIC8vIEBzZWUgaHR0cDovL2pzcGVyZi5jb20vY2FsbC1hcHBseS1zZWd1XG4gICAgICBpZiAoYXJncykge1xuICAgICAgICBmbi5hcHBseShudWxsLCBhcmdzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGZuLmNhbGwobnVsbCk7XG4gICAgICB9XG4gICAgICAvLyBQcmV2ZW50IGlkcyBmcm9tIGxlYWtpbmdcbiAgICAgIGV4cG9ydHMuY2xlYXJJbW1lZGlhdGUoaWQpO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIGlkO1xufTtcblxuZXhwb3J0cy5jbGVhckltbWVkaWF0ZSA9IHR5cGVvZiBjbGVhckltbWVkaWF0ZSA9PT0gXCJmdW5jdGlvblwiID8gY2xlYXJJbW1lZGlhdGUgOiBmdW5jdGlvbihpZCkge1xuICBkZWxldGUgaW1tZWRpYXRlSWRzW2lkXTtcbn07IiwiXG4vKipcbiAqIE1vZHVsZSBleHBvcnRzLlxuICovXG5cbm1vZHVsZS5leHBvcnRzID0gZGVwcmVjYXRlO1xuXG4vKipcbiAqIE1hcmsgdGhhdCBhIG1ldGhvZCBzaG91bGQgbm90IGJlIHVzZWQuXG4gKiBSZXR1cm5zIGEgbW9kaWZpZWQgZnVuY3Rpb24gd2hpY2ggd2FybnMgb25jZSBieSBkZWZhdWx0LlxuICpcbiAqIElmIGBsb2NhbFN0b3JhZ2Uubm9EZXByZWNhdGlvbiA9IHRydWVgIGlzIHNldCwgdGhlbiBpdCBpcyBhIG5vLW9wLlxuICpcbiAqIElmIGBsb2NhbFN0b3JhZ2UudGhyb3dEZXByZWNhdGlvbiA9IHRydWVgIGlzIHNldCwgdGhlbiBkZXByZWNhdGVkIGZ1bmN0aW9uc1xuICogd2lsbCB0aHJvdyBhbiBFcnJvciB3aGVuIGludm9rZWQuXG4gKlxuICogSWYgYGxvY2FsU3RvcmFnZS50cmFjZURlcHJlY2F0aW9uID0gdHJ1ZWAgaXMgc2V0LCB0aGVuIGRlcHJlY2F0ZWQgZnVuY3Rpb25zXG4gKiB3aWxsIGludm9rZSBgY29uc29sZS50cmFjZSgpYCBpbnN0ZWFkIG9mIGBjb25zb2xlLmVycm9yKClgLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZuIC0gdGhlIGZ1bmN0aW9uIHRvIGRlcHJlY2F0ZVxuICogQHBhcmFtIHtTdHJpbmd9IG1zZyAtIHRoZSBzdHJpbmcgdG8gcHJpbnQgdG8gdGhlIGNvbnNvbGUgd2hlbiBgZm5gIGlzIGludm9rZWRcbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gYSBuZXcgXCJkZXByZWNhdGVkXCIgdmVyc2lvbiBvZiBgZm5gXG4gKiBAYXBpIHB1YmxpY1xuICovXG5cbmZ1bmN0aW9uIGRlcHJlY2F0ZSAoZm4sIG1zZykge1xuICBpZiAoY29uZmlnKCdub0RlcHJlY2F0aW9uJykpIHtcbiAgICByZXR1cm4gZm47XG4gIH1cblxuICB2YXIgd2FybmVkID0gZmFsc2U7XG4gIGZ1bmN0aW9uIGRlcHJlY2F0ZWQoKSB7XG4gICAgaWYgKCF3YXJuZWQpIHtcbiAgICAgIGlmIChjb25maWcoJ3Rocm93RGVwcmVjYXRpb24nKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IobXNnKTtcbiAgICAgIH0gZWxzZSBpZiAoY29uZmlnKCd0cmFjZURlcHJlY2F0aW9uJykpIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS53YXJuKG1zZyk7XG4gICAgICB9XG4gICAgICB3YXJuZWQgPSB0cnVlO1xuICAgIH1cbiAgICByZXR1cm4gZm4uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgfVxuXG4gIHJldHVybiBkZXByZWNhdGVkO1xufVxuXG4vKipcbiAqIENoZWNrcyBgbG9jYWxTdG9yYWdlYCBmb3IgYm9vbGVhbiB2YWx1ZXMgZm9yIHRoZSBnaXZlbiBgbmFtZWAuXG4gKlxuICogQHBhcmFtIHtTdHJpbmd9IG5hbWVcbiAqIEByZXR1cm5zIHtCb29sZWFufVxuICogQGFwaSBwcml2YXRlXG4gKi9cblxuZnVuY3Rpb24gY29uZmlnIChuYW1lKSB7XG4gIC8vIGFjY2Vzc2luZyBnbG9iYWwubG9jYWxTdG9yYWdlIGNhbiB0cmlnZ2VyIGEgRE9NRXhjZXB0aW9uIGluIHNhbmRib3hlZCBpZnJhbWVzXG4gIHRyeSB7XG4gICAgaWYgKCFnbG9iYWwubG9jYWxTdG9yYWdlKSByZXR1cm4gZmFsc2U7XG4gIH0gY2F0Y2ggKF8pIHtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cbiAgdmFyIHZhbCA9IGdsb2JhbC5sb2NhbFN0b3JhZ2VbbmFtZV07XG4gIGlmIChudWxsID09IHZhbCkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gU3RyaW5nKHZhbCkudG9Mb3dlckNhc2UoKSA9PT0gJ3RydWUnO1xufVxuIiwibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBpc0J1ZmZlcihhcmcpIHtcbiAgcmV0dXJuIGFyZyAmJiB0eXBlb2YgYXJnID09PSAnb2JqZWN0J1xuICAgICYmIHR5cGVvZiBhcmcuY29weSA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcuZmlsbCA9PT0gJ2Z1bmN0aW9uJ1xuICAgICYmIHR5cGVvZiBhcmcucmVhZFVJbnQ4ID09PSAnZnVuY3Rpb24nO1xufSIsIi8vIENvcHlyaWdodCBKb3llbnQsIEluYy4gYW5kIG90aGVyIE5vZGUgY29udHJpYnV0b3JzLlxuLy9cbi8vIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uIG9idGFpbmluZyBhXG4vLyBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvbiBmaWxlcyAodGhlXG4vLyBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0IHJlc3RyaWN0aW9uLCBpbmNsdWRpbmdcbi8vIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCxcbi8vIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXRcbi8vIHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZVxuLy8gZm9sbG93aW5nIGNvbmRpdGlvbnM6XG4vL1xuLy8gVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmUgaW5jbHVkZWRcbi8vIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuLy9cbi8vIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1Ncbi8vIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0Zcbi8vIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU5cbi8vIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLFxuLy8gREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SXG4vLyBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFXG4vLyBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuXG52YXIgZm9ybWF0UmVnRXhwID0gLyVbc2RqJV0vZztcbmV4cG9ydHMuZm9ybWF0ID0gZnVuY3Rpb24oZikge1xuICBpZiAoIWlzU3RyaW5nKGYpKSB7XG4gICAgdmFyIG9iamVjdHMgPSBbXTtcbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgb2JqZWN0cy5wdXNoKGluc3BlY3QoYXJndW1lbnRzW2ldKSk7XG4gICAgfVxuICAgIHJldHVybiBvYmplY3RzLmpvaW4oJyAnKTtcbiAgfVxuXG4gIHZhciBpID0gMTtcbiAgdmFyIGFyZ3MgPSBhcmd1bWVudHM7XG4gIHZhciBsZW4gPSBhcmdzLmxlbmd0aDtcbiAgdmFyIHN0ciA9IFN0cmluZyhmKS5yZXBsYWNlKGZvcm1hdFJlZ0V4cCwgZnVuY3Rpb24oeCkge1xuICAgIGlmICh4ID09PSAnJSUnKSByZXR1cm4gJyUnO1xuICAgIGlmIChpID49IGxlbikgcmV0dXJuIHg7XG4gICAgc3dpdGNoICh4KSB7XG4gICAgICBjYXNlICclcyc6IHJldHVybiBTdHJpbmcoYXJnc1tpKytdKTtcbiAgICAgIGNhc2UgJyVkJzogcmV0dXJuIE51bWJlcihhcmdzW2krK10pO1xuICAgICAgY2FzZSAnJWonOlxuICAgICAgICB0cnkge1xuICAgICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShhcmdzW2krK10pO1xuICAgICAgICB9IGNhdGNoIChfKSB7XG4gICAgICAgICAgcmV0dXJuICdbQ2lyY3VsYXJdJztcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuICB9KTtcbiAgZm9yICh2YXIgeCA9IGFyZ3NbaV07IGkgPCBsZW47IHggPSBhcmdzWysraV0pIHtcbiAgICBpZiAoaXNOdWxsKHgpIHx8ICFpc09iamVjdCh4KSkge1xuICAgICAgc3RyICs9ICcgJyArIHg7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciArPSAnICcgKyBpbnNwZWN0KHgpO1xuICAgIH1cbiAgfVxuICByZXR1cm4gc3RyO1xufTtcblxuXG4vLyBNYXJrIHRoYXQgYSBtZXRob2Qgc2hvdWxkIG5vdCBiZSB1c2VkLlxuLy8gUmV0dXJucyBhIG1vZGlmaWVkIGZ1bmN0aW9uIHdoaWNoIHdhcm5zIG9uY2UgYnkgZGVmYXVsdC5cbi8vIElmIC0tbm8tZGVwcmVjYXRpb24gaXMgc2V0LCB0aGVuIGl0IGlzIGEgbm8tb3AuXG5leHBvcnRzLmRlcHJlY2F0ZSA9IGZ1bmN0aW9uKGZuLCBtc2cpIHtcbiAgLy8gQWxsb3cgZm9yIGRlcHJlY2F0aW5nIHRoaW5ncyBpbiB0aGUgcHJvY2VzcyBvZiBzdGFydGluZyB1cC5cbiAgaWYgKGlzVW5kZWZpbmVkKGdsb2JhbC5wcm9jZXNzKSkge1xuICAgIHJldHVybiBmdW5jdGlvbigpIHtcbiAgICAgIHJldHVybiBleHBvcnRzLmRlcHJlY2F0ZShmbiwgbXNnKS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH07XG4gIH1cblxuICBpZiAocHJvY2Vzcy5ub0RlcHJlY2F0aW9uID09PSB0cnVlKSB7XG4gICAgcmV0dXJuIGZuO1xuICB9XG5cbiAgdmFyIHdhcm5lZCA9IGZhbHNlO1xuICBmdW5jdGlvbiBkZXByZWNhdGVkKCkge1xuICAgIGlmICghd2FybmVkKSB7XG4gICAgICBpZiAocHJvY2Vzcy50aHJvd0RlcHJlY2F0aW9uKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtc2cpO1xuICAgICAgfSBlbHNlIGlmIChwcm9jZXNzLnRyYWNlRGVwcmVjYXRpb24pIHtcbiAgICAgICAgY29uc29sZS50cmFjZShtc2cpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihtc2cpO1xuICAgICAgfVxuICAgICAgd2FybmVkID0gdHJ1ZTtcbiAgICB9XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG4gIH1cblxuICByZXR1cm4gZGVwcmVjYXRlZDtcbn07XG5cblxudmFyIGRlYnVncyA9IHt9O1xudmFyIGRlYnVnRW52aXJvbjtcbmV4cG9ydHMuZGVidWdsb2cgPSBmdW5jdGlvbihzZXQpIHtcbiAgaWYgKGlzVW5kZWZpbmVkKGRlYnVnRW52aXJvbikpXG4gICAgZGVidWdFbnZpcm9uID0gcHJvY2Vzcy5lbnYuTk9ERV9ERUJVRyB8fCAnJztcbiAgc2V0ID0gc2V0LnRvVXBwZXJDYXNlKCk7XG4gIGlmICghZGVidWdzW3NldF0pIHtcbiAgICBpZiAobmV3IFJlZ0V4cCgnXFxcXGInICsgc2V0ICsgJ1xcXFxiJywgJ2knKS50ZXN0KGRlYnVnRW52aXJvbikpIHtcbiAgICAgIHZhciBwaWQgPSBwcm9jZXNzLnBpZDtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7XG4gICAgICAgIHZhciBtc2cgPSBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpO1xuICAgICAgICBjb25zb2xlLmVycm9yKCclcyAlZDogJXMnLCBzZXQsIHBpZCwgbXNnKTtcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnc1tzZXRdID0gZnVuY3Rpb24oKSB7fTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGRlYnVnc1tzZXRdO1xufTtcblxuXG4vKipcbiAqIEVjaG9zIHRoZSB2YWx1ZSBvZiBhIHZhbHVlLiBUcnlzIHRvIHByaW50IHRoZSB2YWx1ZSBvdXRcbiAqIGluIHRoZSBiZXN0IHdheSBwb3NzaWJsZSBnaXZlbiB0aGUgZGlmZmVyZW50IHR5cGVzLlxuICpcbiAqIEBwYXJhbSB7T2JqZWN0fSBvYmogVGhlIG9iamVjdCB0byBwcmludCBvdXQuXG4gKiBAcGFyYW0ge09iamVjdH0gb3B0cyBPcHRpb25hbCBvcHRpb25zIG9iamVjdCB0aGF0IGFsdGVycyB0aGUgb3V0cHV0LlxuICovXG4vKiBsZWdhY3k6IG9iaiwgc2hvd0hpZGRlbiwgZGVwdGgsIGNvbG9ycyovXG5mdW5jdGlvbiBpbnNwZWN0KG9iaiwgb3B0cykge1xuICAvLyBkZWZhdWx0IG9wdGlvbnNcbiAgdmFyIGN0eCA9IHtcbiAgICBzZWVuOiBbXSxcbiAgICBzdHlsaXplOiBzdHlsaXplTm9Db2xvclxuICB9O1xuICAvLyBsZWdhY3kuLi5cbiAgaWYgKGFyZ3VtZW50cy5sZW5ndGggPj0gMykgY3R4LmRlcHRoID0gYXJndW1lbnRzWzJdO1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA+PSA0KSBjdHguY29sb3JzID0gYXJndW1lbnRzWzNdO1xuICBpZiAoaXNCb29sZWFuKG9wdHMpKSB7XG4gICAgLy8gbGVnYWN5Li4uXG4gICAgY3R4LnNob3dIaWRkZW4gPSBvcHRzO1xuICB9IGVsc2UgaWYgKG9wdHMpIHtcbiAgICAvLyBnb3QgYW4gXCJvcHRpb25zXCIgb2JqZWN0XG4gICAgZXhwb3J0cy5fZXh0ZW5kKGN0eCwgb3B0cyk7XG4gIH1cbiAgLy8gc2V0IGRlZmF1bHQgb3B0aW9uc1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LnNob3dIaWRkZW4pKSBjdHguc2hvd0hpZGRlbiA9IGZhbHNlO1xuICBpZiAoaXNVbmRlZmluZWQoY3R4LmRlcHRoKSkgY3R4LmRlcHRoID0gMjtcbiAgaWYgKGlzVW5kZWZpbmVkKGN0eC5jb2xvcnMpKSBjdHguY29sb3JzID0gZmFsc2U7XG4gIGlmIChpc1VuZGVmaW5lZChjdHguY3VzdG9tSW5zcGVjdCkpIGN0eC5jdXN0b21JbnNwZWN0ID0gdHJ1ZTtcbiAgaWYgKGN0eC5jb2xvcnMpIGN0eC5zdHlsaXplID0gc3R5bGl6ZVdpdGhDb2xvcjtcbiAgcmV0dXJuIGZvcm1hdFZhbHVlKGN0eCwgb2JqLCBjdHguZGVwdGgpO1xufVxuZXhwb3J0cy5pbnNwZWN0ID0gaW5zcGVjdDtcblxuXG4vLyBodHRwOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0FOU0lfZXNjYXBlX2NvZGUjZ3JhcGhpY3Ncbmluc3BlY3QuY29sb3JzID0ge1xuICAnYm9sZCcgOiBbMSwgMjJdLFxuICAnaXRhbGljJyA6IFszLCAyM10sXG4gICd1bmRlcmxpbmUnIDogWzQsIDI0XSxcbiAgJ2ludmVyc2UnIDogWzcsIDI3XSxcbiAgJ3doaXRlJyA6IFszNywgMzldLFxuICAnZ3JleScgOiBbOTAsIDM5XSxcbiAgJ2JsYWNrJyA6IFszMCwgMzldLFxuICAnYmx1ZScgOiBbMzQsIDM5XSxcbiAgJ2N5YW4nIDogWzM2LCAzOV0sXG4gICdncmVlbicgOiBbMzIsIDM5XSxcbiAgJ21hZ2VudGEnIDogWzM1LCAzOV0sXG4gICdyZWQnIDogWzMxLCAzOV0sXG4gICd5ZWxsb3cnIDogWzMzLCAzOV1cbn07XG5cbi8vIERvbid0IHVzZSAnYmx1ZScgbm90IHZpc2libGUgb24gY21kLmV4ZVxuaW5zcGVjdC5zdHlsZXMgPSB7XG4gICdzcGVjaWFsJzogJ2N5YW4nLFxuICAnbnVtYmVyJzogJ3llbGxvdycsXG4gICdib29sZWFuJzogJ3llbGxvdycsXG4gICd1bmRlZmluZWQnOiAnZ3JleScsXG4gICdudWxsJzogJ2JvbGQnLFxuICAnc3RyaW5nJzogJ2dyZWVuJyxcbiAgJ2RhdGUnOiAnbWFnZW50YScsXG4gIC8vIFwibmFtZVwiOiBpbnRlbnRpb25hbGx5IG5vdCBzdHlsaW5nXG4gICdyZWdleHAnOiAncmVkJ1xufTtcblxuXG5mdW5jdGlvbiBzdHlsaXplV2l0aENvbG9yKHN0ciwgc3R5bGVUeXBlKSB7XG4gIHZhciBzdHlsZSA9IGluc3BlY3Quc3R5bGVzW3N0eWxlVHlwZV07XG5cbiAgaWYgKHN0eWxlKSB7XG4gICAgcmV0dXJuICdcXHUwMDFiWycgKyBpbnNwZWN0LmNvbG9yc1tzdHlsZV1bMF0gKyAnbScgKyBzdHIgK1xuICAgICAgICAgICAnXFx1MDAxYlsnICsgaW5zcGVjdC5jb2xvcnNbc3R5bGVdWzFdICsgJ20nO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBzdHI7XG4gIH1cbn1cblxuXG5mdW5jdGlvbiBzdHlsaXplTm9Db2xvcihzdHIsIHN0eWxlVHlwZSkge1xuICByZXR1cm4gc3RyO1xufVxuXG5cbmZ1bmN0aW9uIGFycmF5VG9IYXNoKGFycmF5KSB7XG4gIHZhciBoYXNoID0ge307XG5cbiAgYXJyYXkuZm9yRWFjaChmdW5jdGlvbih2YWwsIGlkeCkge1xuICAgIGhhc2hbdmFsXSA9IHRydWU7XG4gIH0pO1xuXG4gIHJldHVybiBoYXNoO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdFZhbHVlKGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcykge1xuICAvLyBQcm92aWRlIGEgaG9vayBmb3IgdXNlci1zcGVjaWZpZWQgaW5zcGVjdCBmdW5jdGlvbnMuXG4gIC8vIENoZWNrIHRoYXQgdmFsdWUgaXMgYW4gb2JqZWN0IHdpdGggYW4gaW5zcGVjdCBmdW5jdGlvbiBvbiBpdFxuICBpZiAoY3R4LmN1c3RvbUluc3BlY3QgJiZcbiAgICAgIHZhbHVlICYmXG4gICAgICBpc0Z1bmN0aW9uKHZhbHVlLmluc3BlY3QpICYmXG4gICAgICAvLyBGaWx0ZXIgb3V0IHRoZSB1dGlsIG1vZHVsZSwgaXQncyBpbnNwZWN0IGZ1bmN0aW9uIGlzIHNwZWNpYWxcbiAgICAgIHZhbHVlLmluc3BlY3QgIT09IGV4cG9ydHMuaW5zcGVjdCAmJlxuICAgICAgLy8gQWxzbyBmaWx0ZXIgb3V0IGFueSBwcm90b3R5cGUgb2JqZWN0cyB1c2luZyB0aGUgY2lyY3VsYXIgY2hlY2suXG4gICAgICAhKHZhbHVlLmNvbnN0cnVjdG9yICYmIHZhbHVlLmNvbnN0cnVjdG9yLnByb3RvdHlwZSA9PT0gdmFsdWUpKSB7XG4gICAgdmFyIHJldCA9IHZhbHVlLmluc3BlY3QocmVjdXJzZVRpbWVzLCBjdHgpO1xuICAgIGlmICghaXNTdHJpbmcocmV0KSkge1xuICAgICAgcmV0ID0gZm9ybWF0VmFsdWUoY3R4LCByZXQsIHJlY3Vyc2VUaW1lcyk7XG4gICAgfVxuICAgIHJldHVybiByZXQ7XG4gIH1cblxuICAvLyBQcmltaXRpdmUgdHlwZXMgY2Fubm90IGhhdmUgcHJvcGVydGllc1xuICB2YXIgcHJpbWl0aXZlID0gZm9ybWF0UHJpbWl0aXZlKGN0eCwgdmFsdWUpO1xuICBpZiAocHJpbWl0aXZlKSB7XG4gICAgcmV0dXJuIHByaW1pdGl2ZTtcbiAgfVxuXG4gIC8vIExvb2sgdXAgdGhlIGtleXMgb2YgdGhlIG9iamVjdC5cbiAgdmFyIGtleXMgPSBPYmplY3Qua2V5cyh2YWx1ZSk7XG4gIHZhciB2aXNpYmxlS2V5cyA9IGFycmF5VG9IYXNoKGtleXMpO1xuXG4gIGlmIChjdHguc2hvd0hpZGRlbikge1xuICAgIGtleXMgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlOYW1lcyh2YWx1ZSk7XG4gIH1cblxuICAvLyBJRSBkb2Vzbid0IG1ha2UgZXJyb3IgZmllbGRzIG5vbi1lbnVtZXJhYmxlXG4gIC8vIGh0dHA6Ly9tc2RuLm1pY3Jvc29mdC5jb20vZW4tdXMvbGlicmFyeS9pZS9kd3c1MnNidCh2PXZzLjk0KS5hc3B4XG4gIGlmIChpc0Vycm9yKHZhbHVlKVxuICAgICAgJiYgKGtleXMuaW5kZXhPZignbWVzc2FnZScpID49IDAgfHwga2V5cy5pbmRleE9mKCdkZXNjcmlwdGlvbicpID49IDApKSB7XG4gICAgcmV0dXJuIGZvcm1hdEVycm9yKHZhbHVlKTtcbiAgfVxuXG4gIC8vIFNvbWUgdHlwZSBvZiBvYmplY3Qgd2l0aG91dCBwcm9wZXJ0aWVzIGNhbiBiZSBzaG9ydGN1dHRlZC5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwKSB7XG4gICAgaWYgKGlzRnVuY3Rpb24odmFsdWUpKSB7XG4gICAgICB2YXIgbmFtZSA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKCdbRnVuY3Rpb24nICsgbmFtZSArICddJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gICAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgICAgcmV0dXJuIGN0eC5zdHlsaXplKFJlZ0V4cC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh2YWx1ZSksICdyZWdleHAnKTtcbiAgICB9XG4gICAgaWYgKGlzRGF0ZSh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShEYXRlLnByb3RvdHlwZS50b1N0cmluZy5jYWxsKHZhbHVlKSwgJ2RhdGUnKTtcbiAgICB9XG4gICAgaWYgKGlzRXJyb3IodmFsdWUpKSB7XG4gICAgICByZXR1cm4gZm9ybWF0RXJyb3IodmFsdWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBiYXNlID0gJycsIGFycmF5ID0gZmFsc2UsIGJyYWNlcyA9IFsneycsICd9J107XG5cbiAgLy8gTWFrZSBBcnJheSBzYXkgdGhhdCB0aGV5IGFyZSBBcnJheVxuICBpZiAoaXNBcnJheSh2YWx1ZSkpIHtcbiAgICBhcnJheSA9IHRydWU7XG4gICAgYnJhY2VzID0gWydbJywgJ10nXTtcbiAgfVxuXG4gIC8vIE1ha2UgZnVuY3Rpb25zIHNheSB0aGF0IHRoZXkgYXJlIGZ1bmN0aW9uc1xuICBpZiAoaXNGdW5jdGlvbih2YWx1ZSkpIHtcbiAgICB2YXIgbiA9IHZhbHVlLm5hbWUgPyAnOiAnICsgdmFsdWUubmFtZSA6ICcnO1xuICAgIGJhc2UgPSAnIFtGdW5jdGlvbicgKyBuICsgJ10nO1xuICB9XG5cbiAgLy8gTWFrZSBSZWdFeHBzIHNheSB0aGF0IHRoZXkgYXJlIFJlZ0V4cHNcbiAgaWYgKGlzUmVnRXhwKHZhbHVlKSkge1xuICAgIGJhc2UgPSAnICcgKyBSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBkYXRlcyB3aXRoIHByb3BlcnRpZXMgZmlyc3Qgc2F5IHRoZSBkYXRlXG4gIGlmIChpc0RhdGUodmFsdWUpKSB7XG4gICAgYmFzZSA9ICcgJyArIERhdGUucHJvdG90eXBlLnRvVVRDU3RyaW5nLmNhbGwodmFsdWUpO1xuICB9XG5cbiAgLy8gTWFrZSBlcnJvciB3aXRoIG1lc3NhZ2UgZmlyc3Qgc2F5IHRoZSBlcnJvclxuICBpZiAoaXNFcnJvcih2YWx1ZSkpIHtcbiAgICBiYXNlID0gJyAnICsgZm9ybWF0RXJyb3IodmFsdWUpO1xuICB9XG5cbiAgaWYgKGtleXMubGVuZ3RoID09PSAwICYmICghYXJyYXkgfHwgdmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyBicmFjZXNbMV07XG4gIH1cblxuICBpZiAocmVjdXJzZVRpbWVzIDwgMCkge1xuICAgIGlmIChpc1JlZ0V4cCh2YWx1ZSkpIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZShSZWdFeHAucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpLCAncmVnZXhwJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBjdHguc3R5bGl6ZSgnW09iamVjdF0nLCAnc3BlY2lhbCcpO1xuICAgIH1cbiAgfVxuXG4gIGN0eC5zZWVuLnB1c2godmFsdWUpO1xuXG4gIHZhciBvdXRwdXQ7XG4gIGlmIChhcnJheSkge1xuICAgIG91dHB1dCA9IGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpO1xuICB9IGVsc2Uge1xuICAgIG91dHB1dCA9IGtleXMubWFwKGZ1bmN0aW9uKGtleSkge1xuICAgICAgcmV0dXJuIGZvcm1hdFByb3BlcnR5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleSwgYXJyYXkpO1xuICAgIH0pO1xuICB9XG5cbiAgY3R4LnNlZW4ucG9wKCk7XG5cbiAgcmV0dXJuIHJlZHVjZVRvU2luZ2xlU3RyaW5nKG91dHB1dCwgYmFzZSwgYnJhY2VzKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRQcmltaXRpdmUoY3R4LCB2YWx1ZSkge1xuICBpZiAoaXNVbmRlZmluZWQodmFsdWUpKVxuICAgIHJldHVybiBjdHguc3R5bGl6ZSgndW5kZWZpbmVkJywgJ3VuZGVmaW5lZCcpO1xuICBpZiAoaXNTdHJpbmcodmFsdWUpKSB7XG4gICAgdmFyIHNpbXBsZSA9ICdcXCcnICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpLnJlcGxhY2UoL15cInxcIiQvZywgJycpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAucmVwbGFjZSgvXFxcXFwiL2csICdcIicpICsgJ1xcJyc7XG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKHNpbXBsZSwgJ3N0cmluZycpO1xuICB9XG4gIGlmIChpc051bWJlcih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdudW1iZXInKTtcbiAgaWYgKGlzQm9vbGVhbih2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCcnICsgdmFsdWUsICdib29sZWFuJyk7XG4gIC8vIEZvciBzb21lIHJlYXNvbiB0eXBlb2YgbnVsbCBpcyBcIm9iamVjdFwiLCBzbyBzcGVjaWFsIGNhc2UgaGVyZS5cbiAgaWYgKGlzTnVsbCh2YWx1ZSkpXG4gICAgcmV0dXJuIGN0eC5zdHlsaXplKCdudWxsJywgJ251bGwnKTtcbn1cblxuXG5mdW5jdGlvbiBmb3JtYXRFcnJvcih2YWx1ZSkge1xuICByZXR1cm4gJ1snICsgRXJyb3IucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwodmFsdWUpICsgJ10nO1xufVxuXG5cbmZ1bmN0aW9uIGZvcm1hdEFycmF5KGN0eCwgdmFsdWUsIHJlY3Vyc2VUaW1lcywgdmlzaWJsZUtleXMsIGtleXMpIHtcbiAgdmFyIG91dHB1dCA9IFtdO1xuICBmb3IgKHZhciBpID0gMCwgbCA9IHZhbHVlLmxlbmd0aDsgaSA8IGw7ICsraSkge1xuICAgIGlmIChoYXNPd25Qcm9wZXJ0eSh2YWx1ZSwgU3RyaW5nKGkpKSkge1xuICAgICAgb3V0cHV0LnB1c2goZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cyxcbiAgICAgICAgICBTdHJpbmcoaSksIHRydWUpKTtcbiAgICB9IGVsc2Uge1xuICAgICAgb3V0cHV0LnB1c2goJycpO1xuICAgIH1cbiAgfVxuICBrZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KSB7XG4gICAgaWYgKCFrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICBvdXRwdXQucHVzaChmb3JtYXRQcm9wZXJ0eShjdHgsIHZhbHVlLCByZWN1cnNlVGltZXMsIHZpc2libGVLZXlzLFxuICAgICAgICAgIGtleSwgdHJ1ZSkpO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBvdXRwdXQ7XG59XG5cblxuZnVuY3Rpb24gZm9ybWF0UHJvcGVydHkoY3R4LCB2YWx1ZSwgcmVjdXJzZVRpbWVzLCB2aXNpYmxlS2V5cywga2V5LCBhcnJheSkge1xuICB2YXIgbmFtZSwgc3RyLCBkZXNjO1xuICBkZXNjID0gT2JqZWN0LmdldE93blByb3BlcnR5RGVzY3JpcHRvcih2YWx1ZSwga2V5KSB8fCB7IHZhbHVlOiB2YWx1ZVtrZXldIH07XG4gIGlmIChkZXNjLmdldCkge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tHZXR0ZXIvU2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN0ciA9IGN0eC5zdHlsaXplKCdbR2V0dGVyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIGlmIChkZXNjLnNldCkge1xuICAgICAgc3RyID0gY3R4LnN0eWxpemUoJ1tTZXR0ZXJdJywgJ3NwZWNpYWwnKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFoYXNPd25Qcm9wZXJ0eSh2aXNpYmxlS2V5cywga2V5KSkge1xuICAgIG5hbWUgPSAnWycgKyBrZXkgKyAnXSc7XG4gIH1cbiAgaWYgKCFzdHIpIHtcbiAgICBpZiAoY3R4LnNlZW4uaW5kZXhPZihkZXNjLnZhbHVlKSA8IDApIHtcbiAgICAgIGlmIChpc051bGwocmVjdXJzZVRpbWVzKSkge1xuICAgICAgICBzdHIgPSBmb3JtYXRWYWx1ZShjdHgsIGRlc2MudmFsdWUsIG51bGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgc3RyID0gZm9ybWF0VmFsdWUoY3R4LCBkZXNjLnZhbHVlLCByZWN1cnNlVGltZXMgLSAxKTtcbiAgICAgIH1cbiAgICAgIGlmIChzdHIuaW5kZXhPZignXFxuJykgPiAtMSkge1xuICAgICAgICBpZiAoYXJyYXkpIHtcbiAgICAgICAgICBzdHIgPSBzdHIuc3BsaXQoJ1xcbicpLm1hcChmdW5jdGlvbihsaW5lKSB7XG4gICAgICAgICAgICByZXR1cm4gJyAgJyArIGxpbmU7XG4gICAgICAgICAgfSkuam9pbignXFxuJykuc3Vic3RyKDIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHN0ciA9ICdcXG4nICsgc3RyLnNwbGl0KCdcXG4nKS5tYXAoZnVuY3Rpb24obGluZSkge1xuICAgICAgICAgICAgcmV0dXJuICcgICAnICsgbGluZTtcbiAgICAgICAgICB9KS5qb2luKCdcXG4nKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBzdHIgPSBjdHguc3R5bGl6ZSgnW0NpcmN1bGFyXScsICdzcGVjaWFsJyk7XG4gICAgfVxuICB9XG4gIGlmIChpc1VuZGVmaW5lZChuYW1lKSkge1xuICAgIGlmIChhcnJheSAmJiBrZXkubWF0Y2goL15cXGQrJC8pKSB7XG4gICAgICByZXR1cm4gc3RyO1xuICAgIH1cbiAgICBuYW1lID0gSlNPTi5zdHJpbmdpZnkoJycgKyBrZXkpO1xuICAgIGlmIChuYW1lLm1hdGNoKC9eXCIoW2EtekEtWl9dW2EtekEtWl8wLTldKilcIiQvKSkge1xuICAgICAgbmFtZSA9IG5hbWUuc3Vic3RyKDEsIG5hbWUubGVuZ3RoIC0gMik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ25hbWUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgbmFtZSA9IG5hbWUucmVwbGFjZSgvJy9nLCBcIlxcXFwnXCIpXG4gICAgICAgICAgICAgICAgIC5yZXBsYWNlKC9cXFxcXCIvZywgJ1wiJylcbiAgICAgICAgICAgICAgICAgLnJlcGxhY2UoLyheXCJ8XCIkKS9nLCBcIidcIik7XG4gICAgICBuYW1lID0gY3R4LnN0eWxpemUobmFtZSwgJ3N0cmluZycpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBuYW1lICsgJzogJyArIHN0cjtcbn1cblxuXG5mdW5jdGlvbiByZWR1Y2VUb1NpbmdsZVN0cmluZyhvdXRwdXQsIGJhc2UsIGJyYWNlcykge1xuICB2YXIgbnVtTGluZXNFc3QgPSAwO1xuICB2YXIgbGVuZ3RoID0gb3V0cHV0LnJlZHVjZShmdW5jdGlvbihwcmV2LCBjdXIpIHtcbiAgICBudW1MaW5lc0VzdCsrO1xuICAgIGlmIChjdXIuaW5kZXhPZignXFxuJykgPj0gMCkgbnVtTGluZXNFc3QrKztcbiAgICByZXR1cm4gcHJldiArIGN1ci5yZXBsYWNlKC9cXHUwMDFiXFxbXFxkXFxkP20vZywgJycpLmxlbmd0aCArIDE7XG4gIH0sIDApO1xuXG4gIGlmIChsZW5ndGggPiA2MCkge1xuICAgIHJldHVybiBicmFjZXNbMF0gK1xuICAgICAgICAgICAoYmFzZSA9PT0gJycgPyAnJyA6IGJhc2UgKyAnXFxuICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgb3V0cHV0LmpvaW4oJyxcXG4gICcpICtcbiAgICAgICAgICAgJyAnICtcbiAgICAgICAgICAgYnJhY2VzWzFdO1xuICB9XG5cbiAgcmV0dXJuIGJyYWNlc1swXSArIGJhc2UgKyAnICcgKyBvdXRwdXQuam9pbignLCAnKSArICcgJyArIGJyYWNlc1sxXTtcbn1cblxuXG4vLyBOT1RFOiBUaGVzZSB0eXBlIGNoZWNraW5nIGZ1bmN0aW9ucyBpbnRlbnRpb25hbGx5IGRvbid0IHVzZSBgaW5zdGFuY2VvZmBcbi8vIGJlY2F1c2UgaXQgaXMgZnJhZ2lsZSBhbmQgY2FuIGJlIGVhc2lseSBmYWtlZCB3aXRoIGBPYmplY3QuY3JlYXRlKClgLlxuZnVuY3Rpb24gaXNBcnJheShhcikge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheShhcik7XG59XG5leHBvcnRzLmlzQXJyYXkgPSBpc0FycmF5O1xuXG5mdW5jdGlvbiBpc0Jvb2xlYW4oYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnYm9vbGVhbic7XG59XG5leHBvcnRzLmlzQm9vbGVhbiA9IGlzQm9vbGVhbjtcblxuZnVuY3Rpb24gaXNOdWxsKGFyZykge1xuICByZXR1cm4gYXJnID09PSBudWxsO1xufVxuZXhwb3J0cy5pc051bGwgPSBpc051bGw7XG5cbmZ1bmN0aW9uIGlzTnVsbE9yVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09IG51bGw7XG59XG5leHBvcnRzLmlzTnVsbE9yVW5kZWZpbmVkID0gaXNOdWxsT3JVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzTnVtYmVyKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ251bWJlcic7XG59XG5leHBvcnRzLmlzTnVtYmVyID0gaXNOdW1iZXI7XG5cbmZ1bmN0aW9uIGlzU3RyaW5nKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N0cmluZyc7XG59XG5leHBvcnRzLmlzU3RyaW5nID0gaXNTdHJpbmc7XG5cbmZ1bmN0aW9uIGlzU3ltYm9sKGFyZykge1xuICByZXR1cm4gdHlwZW9mIGFyZyA9PT0gJ3N5bWJvbCc7XG59XG5leHBvcnRzLmlzU3ltYm9sID0gaXNTeW1ib2w7XG5cbmZ1bmN0aW9uIGlzVW5kZWZpbmVkKGFyZykge1xuICByZXR1cm4gYXJnID09PSB2b2lkIDA7XG59XG5leHBvcnRzLmlzVW5kZWZpbmVkID0gaXNVbmRlZmluZWQ7XG5cbmZ1bmN0aW9uIGlzUmVnRXhwKHJlKSB7XG4gIHJldHVybiBpc09iamVjdChyZSkgJiYgb2JqZWN0VG9TdHJpbmcocmUpID09PSAnW29iamVjdCBSZWdFeHBdJztcbn1cbmV4cG9ydHMuaXNSZWdFeHAgPSBpc1JlZ0V4cDtcblxuZnVuY3Rpb24gaXNPYmplY3QoYXJnKSB7XG4gIHJldHVybiB0eXBlb2YgYXJnID09PSAnb2JqZWN0JyAmJiBhcmcgIT09IG51bGw7XG59XG5leHBvcnRzLmlzT2JqZWN0ID0gaXNPYmplY3Q7XG5cbmZ1bmN0aW9uIGlzRGF0ZShkKSB7XG4gIHJldHVybiBpc09iamVjdChkKSAmJiBvYmplY3RUb1N0cmluZyhkKSA9PT0gJ1tvYmplY3QgRGF0ZV0nO1xufVxuZXhwb3J0cy5pc0RhdGUgPSBpc0RhdGU7XG5cbmZ1bmN0aW9uIGlzRXJyb3IoZSkge1xuICByZXR1cm4gaXNPYmplY3QoZSkgJiZcbiAgICAgIChvYmplY3RUb1N0cmluZyhlKSA9PT0gJ1tvYmplY3QgRXJyb3JdJyB8fCBlIGluc3RhbmNlb2YgRXJyb3IpO1xufVxuZXhwb3J0cy5pc0Vycm9yID0gaXNFcnJvcjtcblxuZnVuY3Rpb24gaXNGdW5jdGlvbihhcmcpIHtcbiAgcmV0dXJuIHR5cGVvZiBhcmcgPT09ICdmdW5jdGlvbic7XG59XG5leHBvcnRzLmlzRnVuY3Rpb24gPSBpc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBpc1ByaW1pdGl2ZShhcmcpIHtcbiAgcmV0dXJuIGFyZyA9PT0gbnVsbCB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ2Jvb2xlYW4nIHx8XG4gICAgICAgICB0eXBlb2YgYXJnID09PSAnbnVtYmVyJyB8fFxuICAgICAgICAgdHlwZW9mIGFyZyA9PT0gJ3N0cmluZycgfHxcbiAgICAgICAgIHR5cGVvZiBhcmcgPT09ICdzeW1ib2wnIHx8ICAvLyBFUzYgc3ltYm9sXG4gICAgICAgICB0eXBlb2YgYXJnID09PSAndW5kZWZpbmVkJztcbn1cbmV4cG9ydHMuaXNQcmltaXRpdmUgPSBpc1ByaW1pdGl2ZTtcblxuZXhwb3J0cy5pc0J1ZmZlciA9IHJlcXVpcmUoJy4vc3VwcG9ydC9pc0J1ZmZlcicpO1xuXG5mdW5jdGlvbiBvYmplY3RUb1N0cmluZyhvKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobyk7XG59XG5cblxuZnVuY3Rpb24gcGFkKG4pIHtcbiAgcmV0dXJuIG4gPCAxMCA/ICcwJyArIG4udG9TdHJpbmcoMTApIDogbi50b1N0cmluZygxMCk7XG59XG5cblxudmFyIG1vbnRocyA9IFsnSmFuJywgJ0ZlYicsICdNYXInLCAnQXByJywgJ01heScsICdKdW4nLCAnSnVsJywgJ0F1ZycsICdTZXAnLFxuICAgICAgICAgICAgICAnT2N0JywgJ05vdicsICdEZWMnXTtcblxuLy8gMjYgRmViIDE2OjE5OjM0XG5mdW5jdGlvbiB0aW1lc3RhbXAoKSB7XG4gIHZhciBkID0gbmV3IERhdGUoKTtcbiAgdmFyIHRpbWUgPSBbcGFkKGQuZ2V0SG91cnMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldE1pbnV0ZXMoKSksXG4gICAgICAgICAgICAgIHBhZChkLmdldFNlY29uZHMoKSldLmpvaW4oJzonKTtcbiAgcmV0dXJuIFtkLmdldERhdGUoKSwgbW9udGhzW2QuZ2V0TW9udGgoKV0sIHRpbWVdLmpvaW4oJyAnKTtcbn1cblxuXG4vLyBsb2cgaXMganVzdCBhIHRoaW4gd3JhcHBlciB0byBjb25zb2xlLmxvZyB0aGF0IHByZXBlbmRzIGEgdGltZXN0YW1wXG5leHBvcnRzLmxvZyA9IGZ1bmN0aW9uKCkge1xuICBjb25zb2xlLmxvZygnJXMgLSAlcycsIHRpbWVzdGFtcCgpLCBleHBvcnRzLmZvcm1hdC5hcHBseShleHBvcnRzLCBhcmd1bWVudHMpKTtcbn07XG5cblxuLyoqXG4gKiBJbmhlcml0IHRoZSBwcm90b3R5cGUgbWV0aG9kcyBmcm9tIG9uZSBjb25zdHJ1Y3RvciBpbnRvIGFub3RoZXIuXG4gKlxuICogVGhlIEZ1bmN0aW9uLnByb3RvdHlwZS5pbmhlcml0cyBmcm9tIGxhbmcuanMgcmV3cml0dGVuIGFzIGEgc3RhbmRhbG9uZVxuICogZnVuY3Rpb24gKG5vdCBvbiBGdW5jdGlvbi5wcm90b3R5cGUpLiBOT1RFOiBJZiB0aGlzIGZpbGUgaXMgdG8gYmUgbG9hZGVkXG4gKiBkdXJpbmcgYm9vdHN0cmFwcGluZyB0aGlzIGZ1bmN0aW9uIG5lZWRzIHRvIGJlIHJld3JpdHRlbiB1c2luZyBzb21lIG5hdGl2ZVxuICogZnVuY3Rpb25zIGFzIHByb3RvdHlwZSBzZXR1cCB1c2luZyBub3JtYWwgSmF2YVNjcmlwdCBkb2VzIG5vdCB3b3JrIGFzXG4gKiBleHBlY3RlZCBkdXJpbmcgYm9vdHN0cmFwcGluZyAoc2VlIG1pcnJvci5qcyBpbiByMTE0OTAzKS5cbiAqXG4gKiBAcGFyYW0ge2Z1bmN0aW9ufSBjdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHdoaWNoIG5lZWRzIHRvIGluaGVyaXQgdGhlXG4gKiAgICAgcHJvdG90eXBlLlxuICogQHBhcmFtIHtmdW5jdGlvbn0gc3VwZXJDdG9yIENvbnN0cnVjdG9yIGZ1bmN0aW9uIHRvIGluaGVyaXQgcHJvdG90eXBlIGZyb20uXG4gKi9cbmV4cG9ydHMuaW5oZXJpdHMgPSByZXF1aXJlKCdpbmhlcml0cycpO1xuXG5leHBvcnRzLl9leHRlbmQgPSBmdW5jdGlvbihvcmlnaW4sIGFkZCkge1xuICAvLyBEb24ndCBkbyBhbnl0aGluZyBpZiBhZGQgaXNuJ3QgYW4gb2JqZWN0XG4gIGlmICghYWRkIHx8ICFpc09iamVjdChhZGQpKSByZXR1cm4gb3JpZ2luO1xuXG4gIHZhciBrZXlzID0gT2JqZWN0LmtleXMoYWRkKTtcbiAgdmFyIGkgPSBrZXlzLmxlbmd0aDtcbiAgd2hpbGUgKGktLSkge1xuICAgIG9yaWdpbltrZXlzW2ldXSA9IGFkZFtrZXlzW2ldXTtcbiAgfVxuICByZXR1cm4gb3JpZ2luO1xufTtcblxuZnVuY3Rpb24gaGFzT3duUHJvcGVydHkob2JqLCBwcm9wKSB7XG4gIHJldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKTtcbn1cbiJdfQ== diff --git a/build/peerplaysjs-lib.min.js b/build/peerplaysjs-lib.min.js new file mode 100644 index 0000000..e69d03f --- /dev/null +++ b/build/peerplaysjs-lib.min.js @@ -0,0 +1 @@ +!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this).steemJS=e()}}(function(){return function s(o,a,f){function u(t,e){if(!a[t]){if(!o[t]){var r="function"==typeof require&&require;if(!e&&r)return r(t,!0);if(c)return c(t,!0);var n=new Error("Cannot find module '"+t+"'");throw n.code="MODULE_NOT_FOUND",n}var i=a[t]={exports:{}};o[t][0].call(i.exports,function(e){return u(o[t][1][e]||e)},i,i.exports,s,o,a,f)}return a[t].exports}for(var c="function"==typeof require&&require,e=0;e %s (%d bytes)",i.operation_name,t[1],s,s.length/2)}o.tr_buffer=d.transaction.toBuffer(o)}))})}},{key:"id",value:function(){if(!this.tr_buffer)throw new Error("not finalized");return s.sha256(this.tr_buffer).toString("hex").substring(0,40)}},{key:"add_operation",value:function(e){if(this.tr_buffer)throw new Error("already finalized");if(u(e,"operation"),!Array.isArray(e))throw new Error("Expecting array [operation_id, operation]");this.operations.push(e)}},{key:"get_type_operation",value:function(e,t){if(this.tr_buffer)throw new Error("already finalized");u(e,"name"),u(t,"operation");var r=d[e];u(r,"Unknown operation "+e);var n=i.operations[r.operation_name];if(void 0===n)throw new Error("unknown operation: "+r.operation_name);return t.fee||(t.fee={amount:0,asset_id:0}),"proposal_create"===e&&(t.expiration_time||(t.expiration_time=y()+m.expire_in_secs_proposal)),[n,r.fromObject(t)]}},{key:"set_expire_seconds",value:function(e){if(this.tr_buffer)throw new Error("already finalized");return this.expiration=y()+e}},{key:"propose",value:function(e){if(this.tr_buffer)throw new Error("already finalized");if(!this.operations.length)throw new Error("add operation first");u(e,"proposal_create_options"),u(e.fee_paying_account,"proposal_create_options.fee_paying_account");var t=this.operations.map(function(e){return{op:e}});return this.operations=[],this.signatures=[],this.signer_private_keys=[],e.proposed_ops=t,this.add_type_operation("proposal_create",e),this}},{key:"has_proposed_operation",value:function(){for(var e=!1,t=0;tparseInt(c,10)&&(a=f,u="1.3.0")}var i=[];!function e(t){if(Array.isArray(t))for(var r=0;r>1?o.add(i):o,c=e.pointFromX(f,u),l=c.multiply(i);m(e.isInfinity(l),"nR is not a valid curve point");var h=t.negate().mod(i),d=o.modInverse(i),p=c.multiplyTwo(a,s,h).multiply(d);return e.validate(p),p}t.exports={calcPubKeyRecoveryParam:function(e,t,r,n){for(var i=0;i<4;i++)if(s(e,t,r,i).equals(n))return i;throw new Error("Unable to find valid recovery factor")},deterministicGenerateK:p,recoverPubKey:s,sign:function(r,e,n,t){var i,s,o=h.fromBuffer(e),a=r.n,f=r.G,u=(p(r,e,n,function(e){var t=f.multiply(e);return!r.isInfinity(t)&&0!==(i=t.affineX.mod(a)).signum()&&0!==(s=e.modInverse(a).multiply(o.add(n.multiply(i))).mod(a)).signum()},t),a.shiftRight(1));return 0i.length;)e.writeUint8(0)}}},{key:"public_key",value:function(e,t){if(e){if(!t)return r=n.fixed_data(e,33),i.fromBuffer(r);var r=t.toBuffer();e.append(r.toString("binary"),"binary")}}},{key:"ripemd160",value:function(e,t){if(e)return t?void n.fixed_data(e,20,t):n.fixed_data(e,20)}},{key:"sha256",value:function(e,t){if(e)return t?void n.fixed_data(e,32,t):n.fixed_data(e,32)}},{key:"time_point_sec",value:function(e,t){return t?(t=Math.ceil(t/1e3),void e.writeInt32(t)):(t=e.readInt32(),new Date(1e3*t))}}]),n}();n.exports=t}).call(this,r("buffer").Buffer)},{"../../ecc/src/PublicKey":"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/ecc/src/PublicKey.js",buffer:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/dist/serializer/src/SerializerValidation.js":[function(e,t,r){"use strict";var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},i=e("bytebuffer").Long,s=e("../../chain/src/ChainTypes"),o=9007199254740991,a=-9007199254740991,f={is_empty:function(e){return null==e},required:function(e){var t=1>=8;for(;0>=8}for(var o=0;e[o]===c&&o>16&255,s[o++]=t>>8&255,s[o++]=255&t;var u,c;2===i&&(t=l[e.charCodeAt(f)]<<2|l[e.charCodeAt(f+1)]>>4,s[o++]=255&t);1===i&&(t=l[e.charCodeAt(f)]<<10|l[e.charCodeAt(f+1)]<<4|l[e.charCodeAt(f+2)]>>2,s[o++]=t>>8&255,s[o++]=255&t);return s},r.fromByteArray=function(e){for(var t,r=e.length,n=r%3,i=[],s=0,o=r-n;s>2]+a[t<<4&63]+"==")):2===n&&(t=(e[r-2]<<8)+e[r-1],i.push(a[t>>10]+a[t>>4&63]+a[t<<2&63]+"="));return i.join("")};for(var a=[],l=[],h="undefined"!=typeof Uint8Array?Uint8Array:Array,n="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",i=0,s=n.length;i>18&63]+a[i>>12&63]+a[i>>6&63]+a[63&i]);return s.join("")}l["-".charCodeAt(0)]=62,l["_".charCodeAt(0)]=63},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bigi/lib/bigi.js":[function(e,t,r){function w(e,t,r){if(!(this instanceof w))return new w(e,t,r);null!=e&&("number"==typeof e?this.fromNumber(e,t,r):null==t&&"string"!=typeof e?this.fromString(e,256):this.fromString(e,t))}var n=w.prototype;n.__bigi=e("../package.json").version,w.isBigInteger=function(e,t){return e&&e.__bigi&&(!t||e.__bigi===n.__bigi)},w.prototype.am=function(e,t,r,n,i,s){for(;0<=--s;){var o=t*this[e++]+r[n]+i;i=Math.floor(o/67108864),r[n++]=67108863&o}return i},w.prototype.DB=26,w.prototype.DM=67108863;var i=w.prototype.DV=1<<26;w.prototype.FV=Math.pow(2,52),w.prototype.F1=26,w.prototype.F2=0;var s,o,a="0123456789abcdefghijklmnopqrstuvwxyz",f=new Array;for(s="0".charCodeAt(0),o=0;o<=9;++o)f[s++]=o;for(s="a".charCodeAt(0),o=10;o<36;++o)f[s++]=o;for(s="A".charCodeAt(0),o=10;o<36;++o)f[s++]=o;function u(e){return a.charAt(e)}function c(e,t){var r=f[e.charCodeAt(t)];return null==r?-1:r}function y(e){var t=new w;return t.fromInt(e),t}function v(e){var t,r=1;return 0!=(t=e>>>16)&&(e=t,r+=16),0!=(t=e>>8)&&(e=t,r+=8),0!=(t=e>>4)&&(e=t,r+=4),0!=(t=e>>2)&&(e=t,r+=2),0!=(t=e>>1)&&(e=t,r+=1),r}function b(e){this.m=e}function _(e){this.m=e,this.mp=e.invDigit(),this.mpl=32767&this.mp,this.mph=this.mp>>15,this.um=(1<>=16,t+=16),0==(255&e)&&(e>>=8,t+=8),0==(15&e)&&(e>>=4,t+=4),0==(3&e)&&(e>>=2,t+=2),0==(1&e)&&++t,t}function g(e){for(var t=0;0!=e;)e&=e-1,++t;return t}function j(){}function E(e){return e}function B(e){this.r2=new w,this.q3=new w,w.ONE.dlShiftTo(2*e.t,this.r2),this.mu=this.r2.divide(e),this.m=e}b.prototype.convert=function(e){return e.s<0||0<=e.compareTo(this.m)?e.mod(this.m):e},b.prototype.revert=function(e){return e},b.prototype.reduce=function(e){e.divRemTo(this.m,null,e)},b.prototype.mulTo=function(e,t,r){e.multiplyTo(t,r),this.reduce(r)},b.prototype.sqrTo=function(e,t){e.squareTo(t),this.reduce(t)},_.prototype.convert=function(e){var t=new w;return e.abs().dlShiftTo(this.m.t,t),t.divRemTo(this.m,null,t),e.s<0&&0>15)*this.mpl&this.um)<<15)&e.DM;for(e[r=t+this.m.t]+=this.m.am(0,n,e,t,0,this.m.t);e[r]>=e.DV;)e[r]-=e.DV,e[++r]++}e.clamp(),e.drShiftTo(this.m.t,e),0<=e.compareTo(this.m)&&e.subTo(this.m,e)},_.prototype.mulTo=function(e,t,r){e.multiplyTo(t,r),this.reduce(r)},_.prototype.sqrTo=function(e,t){e.squareTo(t),this.reduce(t)},n.copyTo=function(e){for(var t=this.t-1;0<=t;--t)e[t]=this[t];e.t=this.t,e.s=this.s},n.fromInt=function(e){this.t=1,this.s=e<0?-1:0,0n.DB?(n[n.t-1]|=(a&(1<>n.DB-o):n[n.t-1]|=a<=n.DB&&(o-=n.DB))}8==r&&0!=(128&e[0])&&(n.s=-1,0>s|f,f=(n[r]&o)<=r.t)t.t=0;else{var i=e%r.DB,s=r.DB-i,o=(1<>i;for(var a=n+1;a>i;0>=r.DB;if(e.t>=r.DB;i+=r.s}else{for(i+=r.s;n>=r.DB;i-=e.s}t.s=i<0?-1:0,i<-1?t[n++]=r.DV+i:0=t.DV&&(e[r+t.t]-=t.DV,e[r+t.t+1]=1)}0>n.F2:0),d=n.FV/h,p=(1<>f)&&(s=!0,o=u(n));0<=a;)f>(f+=r.DB-t)):(n=r[a]>>(f-=t)&i,f<=0&&(f+=r.DB,--a)),0>3},n.mod=function(e){var t=new w;return this.abs().divRemTo(e,null,t),this.s<0&&02*this.m.t)return e.mod(this.m);if(e.compareTo(this.m)<0)return e;var t=new w;return e.copyTo(t),this.reduce(t),t},B.prototype.revert=function(e){return e},B.prototype.reduce=function(e){var t=this;for(e.drShiftTo(t.m.t-1,t.r2),e.t>t.m.t+1&&(e.t=t.m.t+1,e.clamp()),t.mu.multiplyUpperTo(t.r2,t.m.t+1,t.q3),t.m.multiplyLowerTo(t.q3,t.m.t+1,t.r2);e.compareTo(t.r2)<0;)e.dAddOffset(1,t.m.t+1);for(e.subTo(t.r2,e);0<=e.compareTo(t.m);)e.subTo(t.m,e)},B.prototype.mulTo=function(e,t,r){e.multiplyTo(t,r),this.reduce(r)},B.prototype.sqrTo=function(e,t){e.squareTo(t),this.reduce(t)};var x=[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997],U=(1<<26)/x[x.length-1];n.chunkSize=function(e){return Math.floor(Math.LN2*this.DB/Math.log(e))},n.toRadix=function(e){if(null==e&&(e=10),0==this.signum()||e<2||36=n&&(r.dMultiply(i),r.dAddOffset(a,0),a=o=0))}0e&&n.subTo(w.ONE.shiftLeft(e-1),n);else{var i=new Array,s=7&e;i.length=1+(e>>3),t.nextBytes(i),0>=r.DB;if(e.t>=r.DB;i+=r.s}else{for(i+=r.s;n>=r.DB;i+=e.s}t.s=i<0?-1:0,0=this.DV;)this[t]-=this.DV,++t>=this.t&&(this[this.t++]=0),++this[t]}},n.multiplyLowerTo=function(e,t,r){var n,i=Math.min(this.t+e.t,t);for(r.s=0,r.t=i;0>1)&&(e=x.length);for(var i=new w(null),s=[],o=0;o>24},n.shortValue=function(){return 0==this.t?this.s:this[0]<<16>>16},n.signum=function(){return this.s<0?-1:this.t<=0||1==this.t&&this[0]<=0?0:1},n.toByteArray=function(){var e=this,t=e.t,r=new Array;r[0]=e.s;var n,i=e.DB-t*e.DB%8,s=0;if(0>i)!=(e.s&e.DM)>>i&&(r[s++]=n|e.s<>(i+=e.DB-8)):(n=e[t]>>(i-=8)&255,i<=0&&(i+=e.DB,--t)),0!=(128&n)&&(n|=-256),0===s&&(128&e.s)!=(128&n)&&++s,(0=this.t?0!=this.s:0!=(this[t]&1<>i-f&u:(l=(e[d]&(1<>this.DB+i-f)),a=r;0==(1&l);)l>>=1,--a;if((i-=a)<0&&(i+=this.DB,--d),p)o[l].copyTo(s),p=!1;else{for(;1=r())throw new RangeError("Attempt to allocate Buffer larger than maximum size: 0x"+r().toString(16)+" bytes");return 0|e}function d(e,t){if(l.isBuffer(e))return e.length;if("undefined"!=typeof ArrayBuffer&&"function"==typeof ArrayBuffer.isView&&(ArrayBuffer.isView(e)||e instanceof ArrayBuffer))return e.byteLength;"string"!=typeof e&&(e=""+e);var r=e.length;if(0===r)return 0;for(var n=!1;;)switch(t){case"ascii":case"latin1":case"binary":return r;case"utf8":case"utf-8":case void 0:return C(e).length;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return 2*r;case"hex":return r>>>1;case"base64":return R(e).length;default:if(n)return C(e).length;t=(""+t).toLowerCase(),n=!0}}function p(e,t,r){var n=e[t];e[t]=e[r],e[r]=n}function m(e,t,r,n,i){if(0===e.length)return-1;if("string"==typeof r?(n=r,r=0):2147483647=e.length){if(i)return-1;r=e.length-1}else if(r<0){if(!i)return-1;r=0}if("string"==typeof t&&(t=l.from(t,n)),l.isBuffer(t))return 0===t.length?-1:y(e,t,r,n,i);if("number"==typeof t)return t&=255,l.TYPED_ARRAY_SUPPORT&&"function"==typeof Uint8Array.prototype.indexOf?i?Uint8Array.prototype.indexOf.call(e,t,r):Uint8Array.prototype.lastIndexOf.call(e,t,r):y(e,[t],r,n,i);throw new TypeError("val must be string, number or Buffer")}function y(e,t,r,n,i){var s,o=1,a=e.length,f=t.length;if(void 0!==n&&("ucs2"===(n=String(n).toLowerCase())||"ucs-2"===n||"utf16le"===n||"utf-16le"===n)){if(e.length<2||t.length<2)return-1;a/=o=2,f/=2,r/=2}function u(e,t){return 1===o?e[t]:e.readUInt16BE(t*o)}if(i){var c=-1;for(s=r;s>>10&1023|55296),c=56320|1023&c),n.push(c),i+=l}return function(e){var t=e.length;if(t<=v)return String.fromCharCode.apply(String,e);var r="",n=0;for(;nthis.length)return"";if((void 0===r||r>this.length)&&(r=this.length),r<=0)return"";if((r>>>=0)<=(t>>>=0))return"";for(e||(e="utf8");;)switch(e){case"hex":return B(this,t,r);case"utf8":case"utf-8":return w(this,t,r);case"ascii":return j(this,t,r);case"latin1":case"binary":return E(this,t,r);case"base64":return g(this,t,r);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return x(this,t,r);default:if(n)throw new TypeError("Unknown encoding: "+e);e=(e+"").toLowerCase(),n=!0}}.apply(this,arguments)},l.prototype.equals=function(e){if(!l.isBuffer(e))throw new TypeError("Argument must be a Buffer");return this===e||0===l.compare(this,e)},l.prototype.inspect=function(){var e="",t=q.INSPECT_MAX_BYTES;return 0t&&(e+=" ... ")),""},l.prototype.compare=function(e,t,r,n,i){if(!l.isBuffer(e))throw new TypeError("Argument must be a Buffer");if(void 0===t&&(t=0),void 0===r&&(r=e?e.length:0),void 0===n&&(n=0),void 0===i&&(i=this.length),t<0||r>e.length||n<0||i>this.length)throw new RangeError("out of range index");if(i<=n&&r<=t)return 0;if(i<=n)return-1;if(r<=t)return 1;if(this===e)return 0;for(var s=(i>>>=0)-(n>>>=0),o=(r>>>=0)-(t>>>=0),a=Math.min(s,o),f=this.slice(n,i),u=e.slice(t,r),c=0;cthis.length)throw new RangeError("Attempt to write outside buffer bounds");n||(n="utf8");for(var s,o,a,f,u,c,l,h,d,p=!1;;)switch(n){case"hex":return b(this,e,t,r);case"utf8":case"utf-8":return h=t,d=r,P(C(e,(l=this).length-h),l,h,d);case"ascii":return _(this,e,t,r);case"latin1":case"binary":return _(this,e,t,r);case"base64":return f=this,u=t,c=r,P(R(e),f,u,c);case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return o=t,a=r,P(function(e,t){for(var r,n,i,s=[],o=0;o>8,i=r%256,s.push(i),s.push(n);return s}(e,(s=this).length-o),s,o,a);default:if(p)throw new TypeError("Unknown encoding: "+n);n=(""+n).toLowerCase(),p=!0}},l.prototype.toJSON=function(){return{type:"Buffer",data:Array.prototype.slice.call(this._arr||this,0)}};var v=4096;function j(e,t,r){var n="";r=Math.min(e.length,r);for(var i=t;ie.length)throw new RangeError("Index out of range")}function D(e,t,r,n){t<0&&(t=65535+t+1);for(var i=0,s=Math.min(e.length-r,2);i>>8*(n?i:1-i)}function T(e,t,r,n){t<0&&(t=4294967295+t+1);for(var i=0,s=Math.min(e.length-r,4);i>>8*(n?i:3-i)&255}function S(e,t,r,n,i,s){if(r+n>e.length)throw new RangeError("Index out of range");if(r<0)throw new RangeError("Index out of range")}function I(e,t,r,n,i){return i||S(e,0,r,4),s.write(e,t,r,n,23,4),r+4}function A(e,t,r,n,i){return i||S(e,0,r,8),s.write(e,t,r,n,52,8),r+8}l.prototype.slice=function(e,t){var r,n=this.length;if((e=~~e)<0?(e+=n)<0&&(e=0):n>>8):D(this,e,t,!0),t+2},l.prototype.writeUInt16BE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,2,65535,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):D(this,e,t,!1),t+2},l.prototype.writeUInt32LE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t+3]=e>>>24,this[t+2]=e>>>16,this[t+1]=e>>>8,this[t]=255&e):T(this,e,t,!0),t+4},l.prototype.writeUInt32BE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,4,4294967295,0),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):T(this,e,t,!1),t+4},l.prototype.writeIntLE=function(e,t,r,n){if(e=+e,t|=0,!n){var i=Math.pow(2,8*r-1);k(this,e,t,r,i-1,-i)}var s=0,o=1,a=0;for(this[t]=255&e;++s>0)-a&255;return t+r},l.prototype.writeIntBE=function(e,t,r,n){if(e=+e,t|=0,!n){var i=Math.pow(2,8*r-1);k(this,e,t,r,i-1,-i)}var s=r-1,o=1,a=0;for(this[t+s]=255&e;0<=--s&&(o*=256);)e<0&&0===a&&0!==this[t+s+1]&&(a=1),this[t+s]=(e/o>>0)-a&255;return t+r},l.prototype.writeInt8=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,1,127,-128),l.TYPED_ARRAY_SUPPORT||(e=Math.floor(e)),e<0&&(e=255+e+1),this[t]=255&e,t+1},l.prototype.writeInt16LE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8):D(this,e,t,!0),t+2},l.prototype.writeInt16BE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,2,32767,-32768),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>8,this[t+1]=255&e):D(this,e,t,!1),t+2},l.prototype.writeInt32LE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,4,2147483647,-2147483648),l.TYPED_ARRAY_SUPPORT?(this[t]=255&e,this[t+1]=e>>>8,this[t+2]=e>>>16,this[t+3]=e>>>24):T(this,e,t,!0),t+4},l.prototype.writeInt32BE=function(e,t,r){return e=+e,t|=0,r||k(this,e,t,4,2147483647,-2147483648),e<0&&(e=4294967295+e+1),l.TYPED_ARRAY_SUPPORT?(this[t]=e>>>24,this[t+1]=e>>>16,this[t+2]=e>>>8,this[t+3]=255&e):T(this,e,t,!1),t+4},l.prototype.writeFloatLE=function(e,t,r){return I(this,e,t,!0,r)},l.prototype.writeFloatBE=function(e,t,r){return I(this,e,t,!1,r)},l.prototype.writeDoubleLE=function(e,t,r){return A(this,e,t,!0,r)},l.prototype.writeDoubleBE=function(e,t,r){return A(this,e,t,!1,r)},l.prototype.copy=function(e,t,r,n){if(r||(r=0),n||0===n||(n=this.length),t>=e.length&&(t=e.length),t||(t=0),0=this.length)throw new RangeError("sourceStart out of bounds");if(n<0)throw new RangeError("sourceEnd out of bounds");n>this.length&&(n=this.length),e.length-t>>=0,r=void 0===r?this.length:r>>>0,e||(e=0),"number"==typeof e)for(s=t;s>6|192,63&r|128)}else if(r<65536){if((t-=3)<0)break;s.push(r>>12|224,r>>6&63|128,63&r|128)}else{if(!(r<1114112))throw new Error("Invalid code point");if((t-=4)<0)break;s.push(r>>18|240,r>>12&63|128,r>>6&63|128,63&r|128)}}return s}function R(e){return n.toByteArray(function(e){var t;if((e=(t=e,t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")).replace(O,"")).length<2)return"";for(;e.length%4!=0;)e+="=";return e}(e))}function P(e,t,r,n){for(var i=0;i=t.length||i>=e.length);++i)t[i+r]=e[i];return i}}).call(this,"undefined"!=typeof global?global:"undefined"!=typeof self?self:"undefined"!=typeof window?window:{})},{"base64-js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/base64-js/index.js",ieee754:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ieee754/index.js",isarray:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/isarray/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/string_decoder/index.js":[function(e,t,r){var n=e("buffer").Buffer,i=n.isEncoding||function(e){switch(e&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};var s=r.StringDecoder=function(e){switch(this.encoding=(e||"utf8").toLowerCase().replace(/[-_]/,""),function(e){if(e&&!i(e))throw new Error("Unknown encoding: "+e)}(e),this.encoding){case"utf8":this.surrogateSize=3;break;case"ucs2":case"utf16le":this.surrogateSize=2,this.detectIncompleteChar=a;break;case"base64":this.surrogateSize=3,this.detectIncompleteChar=f;break;default:return void(this.write=o)}this.charBuffer=new n(6),this.charReceived=0,this.charLength=0};function o(e){return e.toString(this.encoding)}function a(e){this.charReceived=e.length%2,this.charLength=this.charReceived?2:0}function f(e){this.charReceived=e.length%3,this.charLength=this.charReceived?3:0}s.prototype.write=function(e){for(var t="";this.charLength;){var r=e.length>=this.charLength-this.charReceived?this.charLength-this.charReceived:e.length;if(e.copy(this.charBuffer,this.charReceived,0,r),this.charReceived+=r,this.charReceived>5==6){this.charLength=2;break}if(t<=2&&r>>4==14){this.charLength=3;break}if(t<=3&&r>>3==30){this.charLength=4;break}}this.charReceived=t},s.prototype.end=function(e){var t="";if(e&&e.length&&(t=this.write(e)),this.charReceived){var r=this.charReceived,n=this.charBuffer,i=this.encoding;t+=n.slice(0,r).toString(i)}return t}},{buffer:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browserify/node_modules/buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bs58/index.js":[function(e,t,r){var n=e("base-x");t.exports=n("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")},{"base-x":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/base-x/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/bytebuffer/dist/bytebuffer.js":[function(t,e,r){var n,i;n=this,i=function(f){"use strict";var p=function(e,t,r){if(void 0===e&&(e=p.DEFAULT_CAPACITY),void 0===t&&(t=p.DEFAULT_ENDIAN),void 0===r&&(r=p.DEFAULT_NOASSERT),!r){if((e|=0)<0)throw RangeError("Illegal capacity");t=!!t,r=!!r}this.buffer=0===e?s:new ArrayBuffer(e),this.view=0===e?null:new Uint8Array(this.buffer),this.offset=0,this.markedOffset=-1,this.limit=e,this.littleEndian=t,this.noAssert=r};p.VERSION="5.0.1",p.LITTLE_ENDIAN=!0,p.BIG_ENDIAN=!1,p.DEFAULT_CAPACITY=16,p.DEFAULT_ENDIAN=p.BIG_ENDIAN,p.DEFAULT_NOASSERT=!1,p.Long=f||null;var o=p.prototype;o.__isByteBuffer__,Object.defineProperty(o,"__isByteBuffer__",{value:!0,enumerable:!1,configurable:!1});var s=new ArrayBuffer(0),r=String.fromCharCode;function a(e){var t=0;return function(){return t>1,c=-7,l=r?i-1:0,h=r?-1:1,d=e[t+l];for(l+=h,s=d&(1<<-c)-1,d>>=-c,c+=a;0>=-c,c+=n;0>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,d=n?0:s-1,p=n?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,o=c):(o=Math.floor(Math.log(t)/Math.LN2),t*(f=Math.pow(2,-o))<1&&(o--,f*=2),2<=(t+=1<=o+l?h/f:h*Math.pow(2,1-l))*f&&(o++,f/=2),c<=o+l?(a=0,o=c):1<=o+l?(a=(t*f-1)*Math.pow(2,i),o+=l):(a=t*Math.pow(2,l-1)*Math.pow(2,i),o=0));8<=i;e[r+d]=255&a,d+=p,a/=256,i-=8);for(o=o<>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}var n,i=t,s=e.length,o=s>>3,a=0;for(t+=this.writeVarint32(s,t);o--;)n=1&!!e[a++]|(1&!!e[a++])<<1|(1&!!e[a++])<<2|(1&!!e[a++])<<3|(1&!!e[a++])<<4|(1&!!e[a++])<<5|(1&!!e[a++])<<6|(1&!!e[a++])<<7,this.writeByte(n,t++);if(a>3,o=0,a=[];for(e+=n.length;s--;)r=this.readByte(e++),a[o++]=!!(1&r),a[o++]=!!(2&r),a[o++]=!!(4&r),a[o++]=!!(8&r),a[o++]=!!(16&r),a[o++]=!!(32&r),a[o++]=!!(64&r),a[o++]=!!(128&r);if(o>f++&1)}return t&&(this.offset=e),a},o.readBytes=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+e>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+"+e+") <= "+this.buffer.byteLength)}var n=this.slice(t,t+e);return r&&(this.offset+=e),n},o.writeBytes=o.append,o.writeInt8=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal value: "+e+" (not an integer)");if(e|=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}t+=1;var n=this.buffer.byteLength;return nt?n:t),t-=1,this.view[t]=e,r&&(this.offset+=1),this},o.writeByte=o.writeInt8,o.readInt8=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+1) <= "+this.buffer.byteLength)}var r=this.view[e];return 128==(128&r)&&(r=-(255-r+1)),t&&(this.offset+=1),r},o.readByte=o.readInt8,o.writeUint8=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal value: "+e+" (not an integer)");if(e>>>=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}t+=1;var n=this.buffer.byteLength;return nt?n:t),t-=1,this.view[t]=e,r&&(this.offset+=1),this},o.writeUInt8=o.writeUint8,o.readUint8=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+1) <= "+this.buffer.byteLength)}var r=this.view[e];return t&&(this.offset+=1),r},o.readUInt8=o.readUint8,o.writeInt16=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal value: "+e+" (not an integer)");if(e|=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}t+=2;var n=this.buffer.byteLength;return nt?n:t),t-=2,this.littleEndian?(this.view[t+1]=(65280&e)>>>8,this.view[t]=255&e):(this.view[t]=(65280&e)>>>8,this.view[t+1]=255&e),r&&(this.offset+=2),this},o.writeShort=o.writeInt16,o.readInt16=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+2>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+2) <= "+this.buffer.byteLength)}var r=0;return this.littleEndian?(r=this.view[e],r|=this.view[e+1]<<8):(r=this.view[e]<<8,r|=this.view[e+1]),32768==(32768&r)&&(r=-(65535-r+1)),t&&(this.offset+=2),r},o.readShort=o.readInt16,o.writeUint16=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal value: "+e+" (not an integer)");if(e>>>=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}t+=2;var n=this.buffer.byteLength;return nt?n:t),t-=2,this.littleEndian?(this.view[t+1]=(65280&e)>>>8,this.view[t]=255&e):(this.view[t]=(65280&e)>>>8,this.view[t+1]=255&e),r&&(this.offset+=2),this},o.writeUInt16=o.writeUint16,o.readUint16=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+2>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+2) <= "+this.buffer.byteLength)}var r=0;return this.littleEndian?(r=this.view[e],r|=this.view[e+1]<<8):(r=this.view[e]<<8,r|=this.view[e+1]),t&&(this.offset+=2),r},o.readUInt16=o.readUint16,o.writeInt32=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal value: "+e+" (not an integer)");if(e|=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}t+=4;var n=this.buffer.byteLength;return nt?n:t),t-=4,this.littleEndian?(this.view[t+3]=e>>>24&255,this.view[t+2]=e>>>16&255,this.view[t+1]=e>>>8&255,this.view[t]=255&e):(this.view[t]=e>>>24&255,this.view[t+1]=e>>>16&255,this.view[t+2]=e>>>8&255,this.view[t+3]=255&e),r&&(this.offset+=4),this},o.writeInt=o.writeInt32,o.readInt32=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+4) <= "+this.buffer.byteLength)}var r=0;return this.littleEndian?(r=this.view[e+2]<<16,r|=this.view[e+1]<<8,r|=this.view[e],r+=this.view[e+3]<<24>>>0):(r=this.view[e+1]<<16,r|=this.view[e+2]<<8,r|=this.view[e+3],r+=this.view[e]<<24>>>0),r|=0,t&&(this.offset+=4),r},o.readInt=o.readInt32,o.writeUint32=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal value: "+e+" (not an integer)");if(e>>>=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}t+=4;var n=this.buffer.byteLength;return nt?n:t),t-=4,this.littleEndian?(this.view[t+3]=e>>>24&255,this.view[t+2]=e>>>16&255,this.view[t+1]=e>>>8&255,this.view[t]=255&e):(this.view[t]=e>>>24&255,this.view[t+1]=e>>>16&255,this.view[t+2]=e>>>8&255,this.view[t+3]=255&e),r&&(this.offset+=4),this},o.writeUInt32=o.writeUint32,o.readUint32=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+4) <= "+this.buffer.byteLength)}var r=0;return this.littleEndian?(r=this.view[e+2]<<16,r|=this.view[e+1]<<8,r|=this.view[e],r+=this.view[e+3]<<24>>>0):(r=this.view[e+1]<<16,r|=this.view[e+2]<<8,r|=this.view[e+3],r+=this.view[e]<<24>>>0),t&&(this.offset+=4),r},o.readUInt32=o.readUint32,f&&(o.writeInt64=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"==typeof e)e=f.fromNumber(e);else if("string"==typeof e)e=f.fromString(e);else if(!(e&&e instanceof f))throw TypeError("Illegal value: "+e+" (not an integer or Long)");if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}"number"==typeof e?e=f.fromNumber(e):"string"==typeof e&&(e=f.fromString(e)),t+=8;var n=this.buffer.byteLength;nt?n:t),t-=8;var i=e.low,s=e.high;return this.littleEndian?(this.view[t+3]=i>>>24&255,this.view[t+2]=i>>>16&255,this.view[t+1]=i>>>8&255,this.view[t]=255&i,t+=4,this.view[t+3]=s>>>24&255,this.view[t+2]=s>>>16&255,this.view[t+1]=s>>>8&255,this.view[t]=255&s):(this.view[t]=s>>>24&255,this.view[t+1]=s>>>16&255,this.view[t+2]=s>>>8&255,this.view[t+3]=255&s,t+=4,this.view[t]=i>>>24&255,this.view[t+1]=i>>>16&255,this.view[t+2]=i>>>8&255,this.view[t+3]=255&i),r&&(this.offset+=8),this},o.writeLong=o.writeInt64,o.readInt64=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+8) <= "+this.buffer.byteLength)}var r=0,n=0;this.littleEndian?(r=this.view[e+2]<<16,r|=this.view[e+1]<<8,r|=this.view[e],r+=this.view[e+3]<<24>>>0,e+=4,n=this.view[e+2]<<16,n|=this.view[e+1]<<8,n|=this.view[e],n+=this.view[e+3]<<24>>>0):(n=this.view[e+1]<<16,n|=this.view[e+2]<<8,n|=this.view[e+3],n+=this.view[e]<<24>>>0,e+=4,r=this.view[e+1]<<16,r|=this.view[e+2]<<8,r|=this.view[e+3],r+=this.view[e]<<24>>>0);var i=new f(r,n,!1);return t&&(this.offset+=8),i},o.readLong=o.readInt64,o.writeUint64=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"==typeof e)e=f.fromNumber(e);else if("string"==typeof e)e=f.fromString(e);else if(!(e&&e instanceof f))throw TypeError("Illegal value: "+e+" (not an integer or Long)");if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}"number"==typeof e?e=f.fromNumber(e):"string"==typeof e&&(e=f.fromString(e)),t+=8;var n=this.buffer.byteLength;nt?n:t),t-=8;var i=e.low,s=e.high;return this.littleEndian?(this.view[t+3]=i>>>24&255,this.view[t+2]=i>>>16&255,this.view[t+1]=i>>>8&255,this.view[t]=255&i,t+=4,this.view[t+3]=s>>>24&255,this.view[t+2]=s>>>16&255,this.view[t+1]=s>>>8&255,this.view[t]=255&s):(this.view[t]=s>>>24&255,this.view[t+1]=s>>>16&255,this.view[t+2]=s>>>8&255,this.view[t+3]=255&s,t+=4,this.view[t]=i>>>24&255,this.view[t+1]=i>>>16&255,this.view[t+2]=i>>>8&255,this.view[t+3]=255&i),r&&(this.offset+=8),this},o.writeUInt64=o.writeUint64,o.readUint64=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+8) <= "+this.buffer.byteLength)}var r=0,n=0;this.littleEndian?(r=this.view[e+2]<<16,r|=this.view[e+1]<<8,r|=this.view[e],r+=this.view[e+3]<<24>>>0,e+=4,n=this.view[e+2]<<16,n|=this.view[e+1]<<8,n|=this.view[e],n+=this.view[e+3]<<24>>>0):(n=this.view[e+1]<<16,n|=this.view[e+2]<<8,n|=this.view[e+3],n+=this.view[e]<<24>>>0,e+=4,r=this.view[e+1]<<16,r|=this.view[e+2]<<8,r|=this.view[e+3],r+=this.view[e]<<24>>>0);var i=new f(r,n,!0);return t&&(this.offset+=8),i},o.readUInt64=o.readUint64),o.writeFloat32=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e)throw TypeError("Illegal value: "+e+" (not a number)");if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}t+=4;var n=this.buffer.byteLength;return nt?n:t),t-=4,i(this.view,e,t,this.littleEndian,23,4),r&&(this.offset+=4),this},o.writeFloat=o.writeFloat32,o.readFloat32=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+4) <= "+this.buffer.byteLength)}var r=n(this.view,e,this.littleEndian,23,4);return t&&(this.offset+=4),r},o.readFloat=o.readFloat32,o.writeFloat64=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e)throw TypeError("Illegal value: "+e+" (not a number)");if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}t+=8;var n=this.buffer.byteLength;return nt?n:t),t-=8,i(this.view,e,t,this.littleEndian,52,8),r&&(this.offset+=8),this},o.writeDouble=o.writeFloat64,o.readFloat64=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+8>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+8) <= "+this.buffer.byteLength)}var r=n(this.view,e,this.littleEndian,52,8);return t&&(this.offset+=8),r},o.readDouble=o.readFloat64,p.MAX_VARINT32_BYTES=5,p.calculateVarint32=function(e){return(e>>>=0)<128?1:e<16384?2:e<1<<21?3:e<1<<28?4:5},p.zigZagEncode32=function(e){return((e|=0)<<1^e>>31)>>>0},p.zigZagDecode32=function(e){return e>>>1^-(1&e)|0},o.writeVarint32=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal value: "+e+" (not an integer)");if(e|=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}var n,i=p.calculateVarint32(e);t+=i;var s=this.buffer.byteLength;for(st?s:t),t-=i,e>>>=0;128<=e;)n=127&e|128,this.view[t++]=n,e>>>=7;return this.view[t++]=e,r?(this.offset=t,this):i},o.writeVarint32ZigZag=function(e,t){return this.writeVarint32(p.zigZagEncode32(e),t)},o.readVarint32=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+1) <= "+this.buffer.byteLength)}var r,n=0,i=0;do{if(!this.noAssert&&e>this.limit){var s=Error("Truncated");throw s.truncated=!0,s}r=this.view[e++],n<5&&(i|=(127&r)<<7*n),++n}while(0!=(128&r));return i|=0,t?(this.offset=e,i):{value:i,length:n}},o.readVarint32ZigZag=function(e){var t=this.readVarint32(e);return"object"==typeof t?t.value=p.zigZagDecode32(t.value):t=p.zigZagDecode32(t),t},f&&(p.MAX_VARINT64_BYTES=10,p.calculateVarint64=function(e){"number"==typeof e?e=f.fromNumber(e):"string"==typeof e&&(e=f.fromString(e));var t=e.toInt()>>>0,r=e.shiftRightUnsigned(28).toInt()>>>0,n=e.shiftRightUnsigned(56).toInt()>>>0;return 0==n?0==r?t<16384?t<128?1:2:t<1<<21?3:4:r<16384?r<128?5:6:r<1<<21?7:8:n<128?9:10},p.zigZagEncode64=function(e){return"number"==typeof e?e=f.fromNumber(e,!1):"string"==typeof e?e=f.fromString(e,!1):!1!==e.unsigned&&(e=e.toSigned()),e.shiftLeft(1).xor(e.shiftRight(63)).toUnsigned()},p.zigZagDecode64=function(e){return"number"==typeof e?e=f.fromNumber(e,!1):"string"==typeof e?e=f.fromString(e,!1):!1!==e.unsigned&&(e=e.toSigned()),e.shiftRightUnsigned(1).xor(e.and(f.ONE).toSigned().negate()).toSigned()},o.writeVarint64=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("number"==typeof e)e=f.fromNumber(e);else if("string"==typeof e)e=f.fromString(e);else if(!(e&&e instanceof f))throw TypeError("Illegal value: "+e+" (not an integer or Long)");if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}"number"==typeof e?e=f.fromNumber(e,!1):"string"==typeof e?e=f.fromString(e,!1):!1!==e.unsigned&&(e=e.toSigned());var n=p.calculateVarint64(e),i=e.toInt()>>>0,s=e.shiftRightUnsigned(28).toInt()>>>0,o=e.shiftRightUnsigned(56).toInt()>>>0;t+=n;var a=this.buffer.byteLength;switch(at?a:t),t-=n,n){case 10:this.view[t+9]=o>>>7&1;case 9:this.view[t+8]=9!==n?128|o:127&o;case 8:this.view[t+7]=8!==n?s>>>21|128:s>>>21&127;case 7:this.view[t+6]=7!==n?s>>>14|128:s>>>14&127;case 6:this.view[t+5]=6!==n?s>>>7|128:s>>>7&127;case 5:this.view[t+4]=5!==n?128|s:127&s;case 4:this.view[t+3]=4!==n?i>>>21|128:i>>>21&127;case 3:this.view[t+2]=3!==n?i>>>14|128:i>>>14&127;case 2:this.view[t+1]=2!==n?i>>>7|128:i>>>7&127;case 1:this.view[t]=1!==n?128|i:127&i}return r?(this.offset+=n,this):n},o.writeVarint64ZigZag=function(e,t){return this.writeVarint64(p.zigZagEncode64(e),t)},o.readVarint64=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+1) <= "+this.buffer.byteLength)}var r=e,n=0,i=0,s=0,o=0;if(n=127&(o=this.view[e++]),128&o&&(n|=(127&(o=this.view[e++]))<<7,(128&o||this.noAssert&&void 0===o)&&(n|=(127&(o=this.view[e++]))<<14,(128&o||this.noAssert&&void 0===o)&&(n|=(127&(o=this.view[e++]))<<21,(128&o||this.noAssert&&void 0===o)&&(i=127&(o=this.view[e++]),(128&o||this.noAssert&&void 0===o)&&(i|=(127&(o=this.view[e++]))<<7,(128&o||this.noAssert&&void 0===o)&&(i|=(127&(o=this.view[e++]))<<14,(128&o||this.noAssert&&void 0===o)&&(i|=(127&(o=this.view[e++]))<<21,(128&o||this.noAssert&&void 0===o)&&(s=127&(o=this.view[e++]),(128&o||this.noAssert&&void 0===o)&&(s|=(127&(o=this.view[e++]))<<7,128&o||this.noAssert&&void 0===o))))))))))throw Error("Buffer overrun");var a=f.fromBits(n|i<<28,i>>>4|s<<24,!1);return t?(this.offset=e,a):{value:a,length:e-r}},o.readVarint64ZigZag=function(e){var t=this.readVarint64(e);return t&&t.value instanceof f?t.value=p.zigZagDecode64(t.value):t=p.zigZagDecode64(t),t}),o.writeCString=function(e,t){var r=void 0===t;r&&(t=this.offset);var n,i=e.length;if(!this.noAssert){if("string"!=typeof e)throw TypeError("Illegal str: Not a string");for(n=0;n>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}i=h.calculateUTF16asUTF8(a(e))[1],t+=i+1;var s=this.buffer.byteLength;return st?s:t),t-=i+1,h.encodeUTF16toUTF8(a(e),function(e){this.view[t++]=e}.bind(this)),this.view[t++]=0,r?(this.offset=t,this):i},o.readCString=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+1) <= "+this.buffer.byteLength)}var r,n=e,i=-1;return h.decodeUTF8toUTF16(function(){if(0===i)return null;if(e>=this.limit)throw RangeError("Illegal range: Truncated data, "+e+" < "+this.limit);return 0===(i=this.view[e++])?null:i}.bind(this),r=u(),!0),t?(this.offset=e,r()):{string:r(),length:e-n}},o.writeIString=function(e,t){var r=void 0===t;if(r&&(t=this.offset),!this.noAssert){if("string"!=typeof e)throw TypeError("Illegal str: Not a string");if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}var n,i=t;n=h.calculateUTF16asUTF8(a(e),this.noAssert)[1],t+=4+n;var s=this.buffer.byteLength;if(st?s:t),t-=4+n,this.littleEndian?(this.view[t+3]=n>>>24&255,this.view[t+2]=n>>>16&255,this.view[t+1]=n>>>8&255,this.view[t]=255&n):(this.view[t]=n>>>24&255,this.view[t+1]=n>>>16&255,this.view[t+2]=n>>>8&255,this.view[t+3]=255&n),t+=4,h.encodeUTF16toUTF8(a(e),function(e){this.view[t++]=e}.bind(this)),t!==i+4+n)throw RangeError("Illegal range: Truncated data, "+t+" == "+(t+4+n));return r?(this.offset=t,this):t-i},o.readIString=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+4>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+4) <= "+this.buffer.byteLength)}var r=e,n=this.readUint32(e),i=this.readUTF8String(n,p.METRICS_BYTES,e+=4);return e+=i.length,t?(this.offset=e,i.string):{string:i.string,length:e-r}},p.METRICS_CHARS="c",p.METRICS_BYTES="b",o.writeUTF8String=function(e,t){var r,n=void 0===t;if(n&&(t=this.offset),!this.noAssert){if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: "+t+" (not an integer)");if((t>>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}var i=t;r=h.calculateUTF16asUTF8(a(e))[1],t+=r;var s=this.buffer.byteLength;return st?s:t),t-=r,h.encodeUTF16toUTF8(a(e),function(e){this.view[t++]=e}.bind(this)),n?(this.offset=t,this):t-i},o.writeString=o.writeUTF8String,p.calculateUTF8Chars=function(e){return h.calculateUTF16asUTF8(a(e))[0]},p.calculateUTF8Bytes=function(e){return h.calculateUTF16asUTF8(a(e))[1]},p.calculateString=p.calculateUTF8Bytes,o.readUTF8String=function(e,t,r){"number"==typeof t&&(r=t,t=void 0);var n=void 0===r;if(n&&(r=this.offset),void 0===t&&(t=p.METRICS_CHARS),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal length: "+e+" (not an integer)");if(e|=0,"number"!=typeof r||r%1!=0)throw TypeError("Illegal offset: "+r+" (not an integer)");if((r>>>=0)<0||r+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+r+" (+0) <= "+this.buffer.byteLength)}var i,s=0,o=r;if(t===p.METRICS_CHARS){if(i=u(),h.decodeUTF8(function(){return s>>=0)<0||r+e>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+r+" (+"+e+") <= "+this.buffer.byteLength)}var a=r+e;if(h.decodeUTF8toUTF16(function(){return r>>=0)<0||t+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+t+" (+0) <= "+this.buffer.byteLength)}var n,i,s=t;n=h.calculateUTF16asUTF8(a(e),this.noAssert)[1],i=p.calculateVarint32(n),t+=i+n;var o=this.buffer.byteLength;if(ot?o:t),t-=i+n,t+=this.writeVarint32(n,t),h.encodeUTF16toUTF8(a(e),function(e){this.view[t++]=e}.bind(this)),t!==s+n+i)throw RangeError("Illegal range: Truncated data, "+t+" == "+(t+n+i));return r?(this.offset=t,this):t-s},o.readVString=function(e){var t=void 0===e;if(t&&(e=this.offset),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal offset: "+e+" (not an integer)");if((e>>>=0)<0||e+1>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+1) <= "+this.buffer.byteLength)}var r=e,n=this.readVarint32(e),i=this.readUTF8String(n.value,p.METRICS_BYTES,e+=n.length);return e+=i.length,t?(this.offset=e,i.string):{string:i.string,length:e-r}},o.append=function(e,t,r){"number"!=typeof t&&"string"==typeof t||(r=t,t=void 0);var n=void 0===r;if(n&&(r=this.offset),!this.noAssert){if("number"!=typeof r||r%1!=0)throw TypeError("Illegal offset: "+r+" (not an integer)");if((r>>>=0)<0||r+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+r+" (+0) <= "+this.buffer.byteLength)}e instanceof p||(e=p.wrap(e,t));var i=e.limit-e.offset;if(i<=0)return this;r+=i;var s=this.buffer.byteLength;return sr?s:r),r-=i,this.view.set(e.view.subarray(e.offset,e.limit),r),e.offset+=i,n&&(this.offset+=i),this},o.appendTo=function(e,t){return e.append(this,t),this},o.assert=function(e){return this.noAssert=!e,this},o.capacity=function(){return this.buffer.byteLength},o.clear=function(){return this.offset=0,this.limit=this.buffer.byteLength,this.markedOffset=-1,this},o.clone=function(e){var t=new p(0,this.littleEndian,this.noAssert);return t.view=e?(t.buffer=new ArrayBuffer(this.buffer.byteLength),new Uint8Array(t.buffer)):(t.buffer=this.buffer,this.view),t.offset=this.offset,t.markedOffset=this.markedOffset,t.limit=this.limit,t},o.compact=function(e,t){if(void 0===e&&(e=this.offset),void 0===t&&(t=this.limit),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal begin: Not an integer");if(e>>>=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal end: Not an integer");if(t>>>=0,e<0||tthis.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+e+" <= "+t+" <= "+this.buffer.byteLength)}if(0===e&&t===this.buffer.byteLength)return this;var r=t-e;if(0===r)return this.buffer=s,this.view=null,0<=this.markedOffset&&(this.markedOffset-=e),this.offset=0,this.limit=0,this;var n=new ArrayBuffer(r),i=new Uint8Array(n);return i.set(this.view.subarray(e,t)),this.buffer=n,this.view=i,0<=this.markedOffset&&(this.markedOffset-=e),this.offset=0,this.limit=r,this},o.copy=function(e,t){if(void 0===e&&(e=this.offset),void 0===t&&(t=this.limit),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal begin: Not an integer");if(e>>>=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal end: Not an integer");if(t>>>=0,e<0||tthis.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+e+" <= "+t+" <= "+this.buffer.byteLength)}if(e===t)return new p(0,this.littleEndian,this.noAssert);var r=t-e,n=new p(r,this.littleEndian,this.noAssert);return n.offset=0,n.limit=r,0<=n.markedOffset&&(n.markedOffset-=e),this.copyTo(n,0,e,t),n},o.copyTo=function(e,t,r,n){var i,s;if(!this.noAssert&&!p.isByteBuffer(e))throw TypeError("Illegal target: Not a ByteBuffer");if(t=(s=void 0===t)?e.offset:0|t,r=(i=void 0===r)?this.offset:0|r,n=void 0===n?this.limit:0|n,t<0||t>e.buffer.byteLength)throw RangeError("Illegal target range: 0 <= "+t+" <= "+e.buffer.byteLength);if(r<0||n>this.buffer.byteLength)throw RangeError("Illegal source range: 0 <= "+r+" <= "+this.buffer.byteLength);var o=n-r;return 0===o?e:(e.ensureCapacity(t+o),e.view.set(this.view.subarray(r,n),t),i&&(this.offset+=o),s&&(e.offset+=o),this)},o.ensureCapacity=function(e){var t=this.buffer.byteLength;return te?t:e):this},o.fill=function(e,t,r){var n=void 0===t;if(n&&(t=this.offset),"string"==typeof e&&0>>=0,"number"!=typeof r||r%1!=0)throw TypeError("Illegal end: Not an integer");if(r>>>=0,t<0||rthis.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+t+" <= "+r+" <= "+this.buffer.byteLength)}if(r<=t)return this;for(;t>>=0)<0||e+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+e+" (+0) <= "+this.buffer.byteLength)}return this.markedOffset=e,this},o.order=function(e){if(!this.noAssert&&"boolean"!=typeof e)throw TypeError("Illegal littleEndian: Not a boolean");return this.littleEndian=!!e,this},o.LE=function(e){return this.littleEndian=void 0===e||!!e,this},o.BE=function(e){return this.littleEndian=void 0!==e&&!e,this},o.prepend=function(e,t,r){"number"!=typeof t&&"string"==typeof t||(r=t,t=void 0);var n=void 0===r;if(n&&(r=this.offset),!this.noAssert){if("number"!=typeof r||r%1!=0)throw TypeError("Illegal offset: "+r+" (not an integer)");if((r>>>=0)<0||r+0>this.buffer.byteLength)throw RangeError("Illegal offset: 0 <= "+r+" (+0) <= "+this.buffer.byteLength)}e instanceof p||(e=p.wrap(e,t));var i=e.limit-e.offset;if(i<=0)return this;var s=i-r;if(0>>=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal end: Not an integer");if(t>>>=0,e<0||tthis.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+e+" <= "+t+" <= "+this.buffer.byteLength)}return e===t||Array.prototype.reverse.call(this.view.subarray(e,t)),this},o.skip=function(e){if(!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal length: "+e+" (not an integer)");e|=0}var t=this.offset+e;if(!this.noAssert&&(t<0||t>this.buffer.byteLength))throw RangeError("Illegal length: 0 <= "+this.offset+" + "+e+" <= "+this.buffer.byteLength);return this.offset=t,this},o.slice=function(e,t){if(void 0===e&&(e=this.offset),void 0===t&&(t=this.limit),!this.noAssert){if("number"!=typeof e||e%1!=0)throw TypeError("Illegal begin: Not an integer");if(e>>>=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal end: Not an integer");if(t>>>=0,e<0||tthis.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+e+" <= "+t+" <= "+this.buffer.byteLength)}var r=this.clone();return r.offset=e,r.limit=t,r},o.toBuffer=function(e){var t=this.offset,r=this.limit;if(!this.noAssert){if("number"!=typeof t||t%1!=0)throw TypeError("Illegal offset: Not an integer");if(t>>>=0,"number"!=typeof r||r%1!=0)throw TypeError("Illegal limit: Not an integer");if(r>>>=0,t<0||rthis.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+t+" <= "+r+" <= "+this.buffer.byteLength)}if(!e&&0===t&&r===this.buffer.byteLength)return this.buffer;if(t===r)return s;var n=new ArrayBuffer(r-t);return new Uint8Array(n).set(new Uint8Array(this.buffer).subarray(t,r),0),n},o.toArrayBuffer=o.toBuffer,o.toString=function(e,t,r){if(void 0===e)return"ByteBufferAB(offset="+this.offset+",markedOffset="+this.markedOffset+",limit="+this.limit+",capacity="+this.capacity()+")";switch("number"==typeof e&&(r=t=e="utf8"),e){case"utf8":return this.toUTF8(t,r);case"base64":return this.toBase64(t,r);case"hex":return this.toHex(t,r);case"binary":return this.toBinary(t,r);case"debug":return this.toDebug();case"columns":return this.toColumns();default:throw Error("Unsupported encoding: "+e)}};var c=function(){for(var e={},i=[65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,48,49,50,51,52,53,54,55,56,57,43,47],o=[],t=0,r=i.length;t>2&63]),n=(3&r)<<4,null!==(r=e())?(t(i[63&((n|=r>>4&15)|r>>4&15)]),n=(15&r)<<2,null!==(r=e())?(t(i[63&(n|r>>6&3)]),t(i[63&r])):(t(i[63&n]),t(61))):(t(i[63&n]),t(61),t(61))},e.decode=function(e,t){var r,n,i;function s(e){throw Error("Illegal character code: "+e)}for(;null!==(r=e());)if(void 0===(n=o[r])&&s(r),null!==(r=e())&&(void 0===(i=o[r])&&s(r),t(n<<2>>>0|(48&i)>>4),null!==(r=e()))){if(void 0===(n=o[r])){if(61===r)break;s(r)}if(t((15&i)<<4>>>0|(60&n)>>2),null!==(r=e())){if(void 0===(i=o[r])){if(61===r)break;s(r)}t((3&n)<<6>>>0|i)}}},e.test=function(e){return/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/.test(e)},e}();o.toBase64=function(e,t){if(void 0===e&&(e=this.offset),void 0===t&&(t=this.limit),t|=0,(e|=0)<0||t>this.capacity||tthis.capacity()||t":i+=r===this.markedOffset?"'":e||0!==r&&r!==n?" ":""}if(e&&" "!==i){for(;i.length<51;)i+=" ";o+=i+s+"\n"}return e?o:i},p.fromDebug=function(e,t,r){for(var n,i,s=e.length,o=new p((s+1)/3|0,t,r),a=0,f=0,u=!1,c=!1,l=!1,h=!1,d=!1;a":if(!r){if(h){d=!0;break}h=!0}o.limit=f,u=!1;break;case"'":if(!r){if(l){d=!0;break}l=!0}o.markedOffset=f,u=!1;break;case" ":u=!1;break;default:if(!r&&u){d=!0;break}if(i=parseInt(n+e.charAt(a++),16),!r&&(isNaN(i)||i<0||255>>=0,"number"!=typeof t||t%1!=0)throw TypeError("Illegal end: Not an integer");if(t>>>=0,e<0||tthis.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+e+" <= "+t+" <= "+this.buffer.byteLength)}for(var r,n=new Array(t-e);e>6&31|192):(r<65536?t(r>>12&15|224):(t(r>>18&7|240),t(r>>12&63|128)),t(r>>6&63|128)),t(63&r|128)),r=null},decodeUTF8:function(e,t){for(var r,n,i,s,o=function(e){e=e.slice(0,e.indexOf(null));var t=Error(e.toString());throw t.name="TruncatedError",t.bytes=e,t};null!==(r=e());)if(0==(128&r))t(r);else if(192==(224&r))null===(n=e())&&o([r,n]),t((31&r)<<6|63&n);else if(224==(240&r))(null===(n=e())||null===(i=e()))&&o([r,n,i]),t((15&r)<<12|(63&n)<<6|63&i);else{if(240!=(248&r))throw RangeError("Illegal starting byte: "+r);(null===(n=e())||null===(i=e())||null===(s=e()))&&o([r,n,i,s]),t((7&r)<<18|(63&n)<<12|(63&i)<<6|63&s)}},UTF16toUTF8:function(e,t){for(var r,n=null;null!==(r=null!==n?n:e());)55296<=r&&r<=57343&&null!==(n=e())&&56320<=n&&n<=57343?(t(1024*(r-55296)+n-56320+65536),n=null):t(r);null!==n&&t(n)},UTF8toUTF16:function(e,t){var r=null;for("number"==typeof e&&(r=e,e=function(){return null});null!==r||null!==(r=e());)r<=65535?t(r):(t(55296+((r-=65536)>>10)),t(r%1024+56320)),r=null},encodeUTF16toUTF8:function(e,t){l.UTF16toUTF8(e,function(e){l.encodeUTF8(e,t)})},decodeUTF8toUTF16:function(e,t){l.decodeUTF8(e,function(e){l.UTF8toUTF16(e,t)})},calculateCodePoint:function(e){return e<128?1:e<2048?2:e<65536?3:4},calculateUTF8:function(e){for(var t,r=0;null!==(t=e());)r+=t<128?1:t<2048?2:t<65536?3:4;return r},calculateUTF16asUTF8:function(e){var t=0,r=0;return l.UTF16toUTF8(e,function(e){++t,r+=e<128?1:e<2048?2:e<65536?3:4}),[t,r]}};return o.toUTF8=function(t,r){if(void 0===t&&(t=this.offset),void 0===r&&(r=this.limit),!this.noAssert){if("number"!=typeof t||t%1!=0)throw TypeError("Illegal begin: Not an integer");if(t>>>=0,"number"!=typeof r||r%1!=0)throw TypeError("Illegal end: Not an integer");if(r>>>=0,t<0||rthis.buffer.byteLength)throw RangeError("Illegal range: 0 <= "+t+" <= "+r+" <= "+this.buffer.byteLength)}var e;try{h.decodeUTF8toUTF16(function(){return tr)?t=("rmd160"===e?new f:u(e)).update(t).digest():t.length>>8^255&i^99,u[r]=i;var s=e[c[i]=r],o=e[s],a=e[o],f=257*e[i]^16843008*i;l[r]=f<<24|f>>>8,h[r]=f<<16|f>>>16,d[r]=f<<8|f>>>24,p[r]=f;f=16843009*a^65537*o^257*s^16843008*r;m[i]=f<<24|f>>>8,y[i]=f<<16|f>>>16,b[i]=f<<8|f>>>24,_[i]=f,r?(r=s^e[e[e[a^s]]],n^=e[e[n]]):r=n=1}}();var g=[0,1,2,4,8,16,32,64,128,27,54],n=r.AES=t.extend({_doReset:function(){if(!this._nRounds||this._keyPriorReset!==this._key){for(var e=this._keyPriorReset=this._key,t=e.words,r=e.sigBytes/4,n=4*((this._nRounds=r+6)+1),i=this._keySchedule=[],s=0;s>>24]<<24|u[o>>>16&255]<<16|u[o>>>8&255]<<8|u[255&o]):(o=u[(o=o<<8|o>>>24)>>>24]<<24|u[o>>>16&255]<<16|u[o>>>8&255]<<8|u[255&o],o^=g[s/r|0]<<24),i[s]=i[s-r]^o}for(var a=this._invKeySchedule=[],f=0;f>>24]]^y[u[o>>>16&255]]^b[u[o>>>8&255]]^_[u[255&o]]}}},encryptBlock:function(e,t){this._doCryptBlock(e,t,this._keySchedule,l,h,d,p,u)},decryptBlock:function(e,t){var r=e[t+1];e[t+1]=e[t+3],e[t+3]=r,this._doCryptBlock(e,t,this._invKeySchedule,m,y,b,_,c);r=e[t+1];e[t+1]=e[t+3],e[t+3]=r},_doCryptBlock:function(e,t,r,n,i,s,o,a){for(var f=this._nRounds,u=e[t]^r[0],c=e[t+1]^r[1],l=e[t+2]^r[2],h=e[t+3]^r[3],d=4,p=1;p>>24]^i[c>>>16&255]^s[l>>>8&255]^o[255&h]^r[d++],y=n[c>>>24]^i[l>>>16&255]^s[h>>>8&255]^o[255&u]^r[d++],b=n[l>>>24]^i[h>>>16&255]^s[u>>>8&255]^o[255&c]^r[d++],_=n[h>>>24]^i[u>>>16&255]^s[c>>>8&255]^o[255&l]^r[d++];u=m,c=y,l=b,h=_}m=(a[u>>>24]<<24|a[c>>>16&255]<<16|a[l>>>8&255]<<8|a[255&h])^r[d++],y=(a[c>>>24]<<24|a[l>>>16&255]<<16|a[h>>>8&255]<<8|a[255&u])^r[d++],b=(a[l>>>24]<<24|a[h>>>16&255]<<16|a[u>>>8&255]<<8|a[255&c])^r[d++],_=(a[h>>>24]<<24|a[u>>>16&255]<<16|a[c>>>8&255]<<8|a[255&l])^r[d++];e[t]=m,e[t+1]=y,e[t+2]=b,e[t+3]=_},keySize:8});e.AES=t._createHelper(n)}(),i.AES},"object"==typeof r?t.exports=r=i(e("./core"),e("./enc-base64"),e("./md5"),e("./evpkdf"),e("./cipher-core")):i(n.CryptoJS)},{"./cipher-core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/cipher-core.js","./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js","./enc-base64":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/enc-base64.js","./evpkdf":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/evpkdf.js","./md5":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/md5.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/cipher-core.js":[function(e,t,r){var n,i;n=this,i=function(e){var t,r,n,f,i,s,o,a,u,c,l,h,d,p,m,y,b,_;e.lib.Cipher||(r=(t=e).lib,n=r.Base,f=r.WordArray,i=r.BufferedBlockAlgorithm,(s=t.enc).Utf8,o=s.Base64,a=t.algo.EvpKDF,u=r.Cipher=i.extend({cfg:n.extend(),createEncryptor:function(e,t){return this.create(this._ENC_XFORM_MODE,e,t)},createDecryptor:function(e,t){return this.create(this._DEC_XFORM_MODE,e,t)},init:function(e,t,r){this.cfg=this.cfg.extend(r),this._xformMode=e,this._key=t,this.reset()},reset:function(){i.reset.call(this),this._doReset()},process:function(e){return this._append(e),this._process()},finalize:function(e){return e&&this._append(e),this._doFinalize()},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function i(e){return"string"==typeof e?_:y}return function(n){return{encrypt:function(e,t,r){return i(t).encrypt(n,e,t,r)},decrypt:function(e,t,r){return i(t).decrypt(n,e,t,r)}}}}()}),r.StreamCipher=u.extend({_doFinalize:function(){return this._process(!0)},blockSize:1}),c=t.mode={},l=r.BlockCipherMode=n.extend({createEncryptor:function(e,t){return this.Encryptor.create(e,t)},createDecryptor:function(e,t){return this.Decryptor.create(e,t)},init:function(e,t){this._cipher=e,this._iv=t}}),h=c.CBC=function(){var e=l.extend();function s(e,t,r){var n=this._iv;if(n){var i=n;this._iv=void 0}else i=this._prevBlock;for(var s=0;s>>2];e.sigBytes-=t}},r.BlockCipher=u.extend({cfg:u.cfg.extend({mode:h,padding:d}),reset:function(){u.reset.call(this);var e=this.cfg,t=e.iv,r=e.mode;if(this._xformMode==this._ENC_XFORM_MODE)var n=r.createEncryptor;else{n=r.createDecryptor;this._minBufferSize=1}this._mode=n.call(r,this,t&&t.words)},_doProcessBlock:function(e,t){this._mode.processBlock(e,t)},_doFinalize:function(){var e=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){e.pad(this._data,this.blockSize);var t=this._process(!0)}else{t=this._process(!0);e.unpad(t)}return t},blockSize:4}),p=r.CipherParams=n.extend({init:function(e){this.mixIn(e)},toString:function(e){return(e||this.formatter).stringify(this)}}),m=(t.format={}).OpenSSL={stringify:function(e){var t=e.ciphertext,r=e.salt;if(r)var n=f.create([1398893684,1701076831]).concat(r).concat(t);else n=t;return n.toString(o)},parse:function(e){var t=o.parse(e),r=t.words;if(1398893684==r[0]&&1701076831==r[1]){var n=f.create(r.slice(2,4));r.splice(0,4),t.sigBytes-=16}return p.create({ciphertext:t,salt:n})}},y=r.SerializableCipher=n.extend({cfg:n.extend({format:m}),encrypt:function(e,t,r,n){n=this.cfg.extend(n);var i=e.createEncryptor(r,n),s=i.finalize(t),o=i.cfg;return p.create({ciphertext:s,key:r,iv:o.iv,algorithm:e,mode:o.mode,padding:o.padding,blockSize:e.blockSize,formatter:n.format})},decrypt:function(e,t,r,n){return n=this.cfg.extend(n),t=this._parse(t,n.format),e.createDecryptor(r,n).finalize(t.ciphertext)},_parse:function(e,t){return"string"==typeof e?t.parse(e,this):e}}),b=(t.kdf={}).OpenSSL={execute:function(e,t,r,n){n||(n=f.random(8));var i=a.create({keySize:t+r}).compute(e,n),s=f.create(i.words.slice(t),4*r);return i.sigBytes=4*t,p.create({key:i,iv:s,salt:n})}},_=r.PasswordBasedCipher=y.extend({cfg:y.cfg.extend({kdf:b}),encrypt:function(e,t,r,n){var i=(n=this.cfg.extend(n)).kdf.execute(r,e.keySize,e.ivSize);n.iv=i.iv;var s=y.encrypt.call(this,e,t,i.key,n);return s.mixIn(i),s},decrypt:function(e,t,r,n){n=this.cfg.extend(n),t=this._parse(t,n.format);var i=n.kdf.execute(r,e.keySize,e.ivSize,t.salt);return n.iv=i.iv,y.decrypt.call(this,e,t,i.key,n)}}))},"object"==typeof r?t.exports=r=i(e("./core")):i(n.CryptoJS)},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js":[function(e,t,r){var n,i;n=this,i=function(){var c,r,e,t,n,l,i,s,o,a,f,u,h=h||(c=Math,r=Object.create||function(){function r(){}return function(e){var t;return r.prototype=e,t=new r,r.prototype=null,t}}(),t=(e={}).lib={},n=t.Base={extend:function(e){var t=r(this);return e&&t.mixIn(e),t.hasOwnProperty("init")&&this.init!==t.init||(t.init=function(){t.$super.init.apply(this,arguments)}),(t.init.prototype=t).$super=this,t},create:function(){var e=this.extend();return e.init.apply(e,arguments),e},init:function(){},mixIn:function(e){for(var t in e)e.hasOwnProperty(t)&&(this[t]=e[t]);e.hasOwnProperty("toString")&&(this.toString=e.toString)},clone:function(){return this.init.prototype.extend(this)}},l=t.WordArray=n.extend({init:function(e,t){e=this.words=e||[],this.sigBytes=null!=t?t:4*e.length},toString:function(e){return(e||s).stringify(this)},concat:function(e){var t=this.words,r=e.words,n=this.sigBytes,i=e.sigBytes;if(this.clamp(),n%4)for(var s=0;s>>2]>>>24-s%4*8&255;t[n+s>>>2]|=o<<24-(n+s)%4*8}else for(s=0;s>>2]=r[s>>>2];return this.sigBytes+=i,this},clamp:function(){var e=this.words,t=this.sigBytes;e[t>>>2]&=4294967295<<32-t%4*8,e.length=c.ceil(t/4)},clone:function(){var e=n.clone.call(this);return e.words=this.words.slice(0),e},random:function(e){for(var t,r=[],n=function(t){t=t;var r=987654321,n=4294967295;return function(){var e=((r=36969*(65535&r)+(r>>16)&n)<<16)+(t=18e3*(65535&t)+(t>>16)&n)&n;return e/=4294967296,(e+=.5)*(.5>>2]>>>24-i%4*8&255;n.push((s>>>4).toString(16)),n.push((15&s).toString(16))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n>>3]|=parseInt(e.substr(n,2),16)<<24-n%8*4;return new l.init(r,t/2)}},o=i.Latin1={stringify:function(e){for(var t=e.words,r=e.sigBytes,n=[],i=0;i>>2]>>>24-i%4*8&255;n.push(String.fromCharCode(s))}return n.join("")},parse:function(e){for(var t=e.length,r=[],n=0;n>>2]|=(255&e.charCodeAt(n))<<24-n%4*8;return new l.init(r,t)}},a=i.Utf8={stringify:function(e){try{return decodeURIComponent(escape(o.stringify(e)))}catch(e){throw new Error("Malformed UTF-8 data")}},parse:function(e){return o.parse(unescape(encodeURIComponent(e)))}},f=t.BufferedBlockAlgorithm=n.extend({reset:function(){this._data=new l.init,this._nDataBytes=0},_append:function(e){"string"==typeof e&&(e=a.parse(e)),this._data.concat(e),this._nDataBytes+=e.sigBytes},_process:function(e){var t=this._data,r=t.words,n=t.sigBytes,i=this.blockSize,s=n/(4*i),o=(s=e?c.ceil(s):c.max((0|s)-this._minBufferSize,0))*i,a=c.min(4*o,n);if(o){for(var f=0;f>>2]>>>24-s%4*8&255)<<16|(t[s+1>>>2]>>>24-(s+1)%4*8&255)<<8|t[s+2>>>2]>>>24-(s+2)%4*8&255,a=0;a<4&&s+.75*a>>6*(3-a)&63));var f=n.charAt(64);if(f)for(;i.length%4;)i.push(f);return i.join("")},parse:function(e){var t=e.length,r=this._map,n=this._reverseMap;if(!n){n=this._reverseMap=[];for(var i=0;i>>6-s%4*2;n[i>>>2]|=(o|a)<<24-i%4*8,i++}return f.create(n,i)}(e,t,n)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},e.enc.Base64},"object"==typeof r?t.exports=r=i(e("./core")):i(n.CryptoJS)},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/enc-hex.js":[function(e,t,r){var n,i;n=this,i=function(e){return e.enc.Hex},"object"==typeof r?t.exports=r=i(e("./core")):i(n.CryptoJS)},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/evpkdf.js":[function(e,t,r){var n,i;n=this,i=function(e){var t,r,n,c,i,s,o;return r=(t=e).lib,n=r.Base,c=r.WordArray,i=t.algo,s=i.MD5,o=i.EvpKDF=n.extend({cfg:n.extend({keySize:4,hasher:s,iterations:1}),init:function(e){this.cfg=this.cfg.extend(e)},compute:function(e,t){for(var r=this.cfg,n=r.hasher.create(),i=c.create(),s=i.words,o=r.keySize,a=r.iterations;s.lengthn&&(t=e.finalize(t)),t.clamp();for(var i=this._oKey=t.clone(),s=this._iKey=t.clone(),o=i.words,a=s.words,f=0;f>>24)|4278255360&(i<<24|i>>>8)}var s=this._hash.words,o=e[t+0],a=e[t+1],f=e[t+2],u=e[t+3],c=e[t+4],l=e[t+5],h=e[t+6],d=e[t+7],p=e[t+8],m=e[t+9],y=e[t+10],b=e[t+11],_=e[t+12],g=e[t+13],w=e[t+14],v=e[t+15],j=s[0],E=s[1],B=s[2],x=s[3];E=S(E=S(E=S(E=S(E=T(E=T(E=T(E=T(E=D(E=D(E=D(E=D(E=k(E=k(E=k(E=k(E,B=k(B,x=k(x,j=k(j,E,B,x,o,7,U[0]),E,B,a,12,U[1]),j,E,f,17,U[2]),x,j,u,22,U[3]),B=k(B,x=k(x,j=k(j,E,B,x,c,7,U[4]),E,B,l,12,U[5]),j,E,h,17,U[6]),x,j,d,22,U[7]),B=k(B,x=k(x,j=k(j,E,B,x,p,7,U[8]),E,B,m,12,U[9]),j,E,y,17,U[10]),x,j,b,22,U[11]),B=k(B,x=k(x,j=k(j,E,B,x,_,7,U[12]),E,B,g,12,U[13]),j,E,w,17,U[14]),x,j,v,22,U[15]),B=D(B,x=D(x,j=D(j,E,B,x,a,5,U[16]),E,B,h,9,U[17]),j,E,b,14,U[18]),x,j,o,20,U[19]),B=D(B,x=D(x,j=D(j,E,B,x,l,5,U[20]),E,B,y,9,U[21]),j,E,v,14,U[22]),x,j,c,20,U[23]),B=D(B,x=D(x,j=D(j,E,B,x,m,5,U[24]),E,B,w,9,U[25]),j,E,u,14,U[26]),x,j,p,20,U[27]),B=D(B,x=D(x,j=D(j,E,B,x,g,5,U[28]),E,B,f,9,U[29]),j,E,d,14,U[30]),x,j,_,20,U[31]),B=T(B,x=T(x,j=T(j,E,B,x,l,4,U[32]),E,B,p,11,U[33]),j,E,b,16,U[34]),x,j,w,23,U[35]),B=T(B,x=T(x,j=T(j,E,B,x,a,4,U[36]),E,B,c,11,U[37]),j,E,d,16,U[38]),x,j,y,23,U[39]),B=T(B,x=T(x,j=T(j,E,B,x,g,4,U[40]),E,B,o,11,U[41]),j,E,u,16,U[42]),x,j,h,23,U[43]),B=T(B,x=T(x,j=T(j,E,B,x,m,4,U[44]),E,B,_,11,U[45]),j,E,v,16,U[46]),x,j,f,23,U[47]),B=S(B,x=S(x,j=S(j,E,B,x,o,6,U[48]),E,B,d,10,U[49]),j,E,w,15,U[50]),x,j,l,21,U[51]),B=S(B,x=S(x,j=S(j,E,B,x,_,6,U[52]),E,B,u,10,U[53]),j,E,y,15,U[54]),x,j,a,21,U[55]),B=S(B,x=S(x,j=S(j,E,B,x,p,6,U[56]),E,B,v,10,U[57]),j,E,h,15,U[58]),x,j,g,21,U[59]),B=S(B,x=S(x,j=S(j,E,B,x,c,6,U[60]),E,B,b,10,U[61]),j,E,f,15,U[62]),x,j,m,21,U[63]),s[0]=s[0]+j|0,s[1]=s[1]+E|0,s[2]=s[2]+B|0,s[3]=s[3]+x|0},_doFinalize:function(){var e=this._data,t=e.words,r=8*this._nDataBytes,n=8*e.sigBytes;t[n>>>5]|=128<<24-n%32;var i=c.floor(r/4294967296),s=r;t[15+(n+64>>>9<<4)]=16711935&(i<<8|i>>>24)|4278255360&(i<<24|i>>>8),t[14+(n+64>>>9<<4)]=16711935&(s<<8|s>>>24)|4278255360&(s<<24|s>>>8),e.sigBytes=4*(t.length+1),this._process();for(var o=this._hash,a=o.words,f=0;f<4;f++){var u=a[f];a[f]=16711935&(u<<8|u>>>24)|4278255360&(u<<24|u>>>8)}return o},clone:function(){var e=n.clone.call(this);return e._hash=this._hash.clone(),e}});function k(e,t,r,n,i,s,o){var a=e+(t&r|~t&n)+i+o;return(a<>>32-s)+t}function D(e,t,r,n,i,s,o){var a=e+(t&n|r&~n)+i+o;return(a<>>32-s)+t}function T(e,t,r,n,i,s,o){var a=e+(t^r^n)+i+o;return(a<>>32-s)+t}function S(e,t,r,n,i,s,o){var a=e+(r^(t|~n))+i+o;return(a<>>32-s)+t}e.MD5=n._createHelper(s),e.HmacMD5=n._createHmacHelper(s)}(Math),o.MD5},"object"==typeof r?t.exports=r=i(e("./core")):i(n.CryptoJS)},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/sha1.js":[function(e,t,r){var n,i;n=this,i=function(e){var t,r,n,i,s,l,o;return r=(t=e).lib,n=r.WordArray,i=r.Hasher,s=t.algo,l=[],o=s.SHA1=i.extend({_doReset:function(){this._hash=new n.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(e,t){for(var r=this._hash.words,n=r[0],i=r[1],s=r[2],o=r[3],a=r[4],f=0;f<80;f++){if(f<16)l[f]=0|e[t+f];else{var u=l[f-3]^l[f-8]^l[f-14]^l[f-16];l[f]=u<<1|u>>>31}var c=(n<<5|n>>>27)+a+l[f];c+=f<20?1518500249+(i&s|~i&o):f<40?1859775393+(i^s^o):f<60?(i&s|i&o|s&o)-1894007588:(i^s^o)-899497514,a=o,o=s,s=i<<30|i>>>2,i=n,n=c}r[0]=r[0]+n|0,r[1]=r[1]+i|0,r[2]=r[2]+s|0,r[3]=r[3]+o|0,r[4]=r[4]+a|0},_doFinalize:function(){var e=this._data,t=e.words,r=8*this._nDataBytes,n=8*e.sigBytes;return t[n>>>5]|=128<<24-n%32,t[14+(n+64>>>9<<4)]=Math.floor(r/4294967296),t[15+(n+64>>>9<<4)]=r,e.sigBytes=4*t.length,this._process(),this._hash},clone:function(){var e=i.clone.call(this);return e._hash=this._hash.clone(),e}}),t.SHA1=i._createHelper(o),t.HmacSHA1=i._createHmacHelper(o),e.SHA1},"object"==typeof r?t.exports=r=i(e("./core")):i(n.CryptoJS)},{"./core":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/crypto-js/core.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/deep-equal/index.js":[function(e,t,r){var a=Array.prototype.slice,f=e("./lib/keys.js"),u=e("./lib/is_arguments.js"),c=t.exports=function(e,t,r){return r||(r={}),e===t||(e instanceof Date&&t instanceof Date?e.getTime()===t.getTime():!e||!t||"object"!=typeof e&&"object"!=typeof t?r.strict?e===t:e==t:function(e,t,r){var n,i;if(l(e)||l(t))return!1;if(e.prototype!==t.prototype)return!1;if(u(e))return!!u(t)&&(e=a.call(e),t=a.call(t),c(e,t,r));if(h(e)){if(!h(t))return!1;if(e.length!==t.length)return!1;for(n=0;nr&&(this._events[e].warned=!0,console.error("(node) warning: possible EventEmitter memory leak detected. %d listeners added. Use emitter.setMaxListeners() to increase limit.",this._events[e].length),"function"==typeof console.trace&&console.trace()),this},n.prototype.once=function(e,t){if(!f(t))throw TypeError("listener must be a function");var r=!1;function n(){this.removeListener(e,n),r||(r=!0,t.apply(this,arguments))}return n.listener=t,this.on(e,n),this},n.prototype.removeListener=function(e,t){var r,n,i,s;if(!f(t))throw TypeError("listener must be a function");if(!this._events||!this._events[e])return this;if(i=(r=this._events[e]).length,n=-1,r===t||f(r.listener)&&r.listener===t)delete this._events[e],this._events.removeListener&&this.emit("removeListener",e,t);else if(u(r)){for(s=i;0=this._blockSize;){for(var i=this._blockOffset;i>1,c=-7,l=r?i-1:0,h=r?-1:1,d=e[t+l];for(l+=h,s=d&(1<<-c)-1,d>>=-c,c+=a;0>=-c,c+=n;0>1,h=23===i?Math.pow(2,-24)-Math.pow(2,-77):0,d=n?0:s-1,p=n?1:-1,m=t<0||0===t&&1/t<0?1:0;for(t=Math.abs(t),isNaN(t)||t===1/0?(a=isNaN(t)?1:0,o=c):(o=Math.floor(Math.log(t)/Math.LN2),t*(f=Math.pow(2,-o))<1&&(o--,f*=2),2<=(t+=1<=o+l?h/f:h*Math.pow(2,1-l))*f&&(o++,f/=2),c<=o+l?(a=0,o=c):1<=o+l?(a=(t*f-1)*Math.pow(2,i),o+=l):(a=t*Math.pow(2,l-1)*Math.pow(2,i),o=0));8<=i;e[r+d]=255&a,d+=p,a/=256,i-=8);for(o=o<>>=0)&&e<256)&&(n=o[e])?n:(r=m(e,(0|e)<0?-1:0,!0),i&&(o[e]=r),r):(i=-128<=(e|=0)&&e<128)&&(n=s[e])?n:(r=m(e,e<0?-1:0,!1),i&&(s[e]=r),r)}function p(e,t){if(isNaN(e)||!isFinite(e))return t?f:_;if(t){if(e<0)return f;if(i<=e)return v}else{if(e<=-a)return j;if(a<=e+1)return w}return e<0?p(-e,t).neg():m(e%r|0,e/r|0,t)}function m(e,t,r){return new n(e,t,r)}n.fromInt=e,n.fromNumber=p,n.fromBits=m;var c=Math.pow;function l(e,t,r){if(0===e.length)throw Error("empty string");if("NaN"===e||"Infinity"===e||"+Infinity"===e||"-Infinity"===e)return _;if(t="number"==typeof t?(r=t,!1):!!t,(r=r||10)<2||36>>0:this.low},t.toNumber=function(){return this.unsigned?(this.high>>>0)*r+(this.low>>>0):this.high*r+(this.low>>>0)},t.toString=function(e){if((e=e||10)<2||36>>0).toString(e);if((s=a).isZero())return f+o;for(;f.length<6;)f="0"+f;o=""+f+o}},t.getHighBits=function(){return this.high},t.getHighBitsUnsigned=function(){return this.high>>>0},t.getLowBits=function(){return this.low},t.getLowBitsUnsigned=function(){return this.low>>>0},t.getNumBitsAbs=function(){if(this.isNegative())return this.eq(j)?64:this.neg().getNumBitsAbs();for(var e=0!=this.high?this.high:this.low,t=31;0>>31!=1||e.high>>>31!=1)&&(this.high===e.high&&this.low===e.low)},t.eq=t.equals,t.notEquals=function(e){return!this.eq(e)},t.neq=t.notEquals,t.lessThan=function(e){return this.comp(e)<0},t.lt=t.lessThan,t.lessThanOrEqual=function(e){return this.comp(e)<=0},t.lte=t.lessThanOrEqual,t.greaterThan=function(e){return 0>>0>this.high>>>0||e.high===this.high&&e.low>>>0>this.low>>>0?-1:1:this.sub(e).isNegative()?-1:1},t.comp=t.compare,t.negate=function(){return!this.unsigned&&this.eq(j)?j:this.not().add(u)},t.neg=t.negate,t.add=function(e){d(e)||(e=y(e));var t=this.high>>>16,r=65535&this.high,n=this.low>>>16,i=65535&this.low,s=e.high>>>16,o=65535&e.high,a=e.low>>>16,f=0,u=0,c=0,l=0;return c+=(l+=i+(65535&e.low))>>>16,u+=(c+=n+a)>>>16,f+=(u+=r+o)>>>16,f+=t+s,m((c&=65535)<<16|(l&=65535),(f&=65535)<<16|(u&=65535),this.unsigned)},t.subtract=function(e){return d(e)||(e=y(e)),this.add(e.neg())},t.sub=t.subtract,t.multiply=function(e){if(this.isZero())return _;if(d(e)||(e=y(e)),e.isZero())return _;if(this.eq(j))return e.isOdd()?j:_;if(e.eq(j))return this.isOdd()?j:_;if(this.isNegative())return e.isNegative()?this.neg().mul(e.neg()):this.neg().mul(e).neg();if(e.isNegative())return this.mul(e.neg()).neg();if(this.lt(b)&&e.lt(b))return p(this.toNumber()*e.toNumber(),this.unsigned);var t=this.high>>>16,r=65535&this.high,n=this.low>>>16,i=65535&this.low,s=e.high>>>16,o=65535&e.high,a=e.low>>>16,f=65535&e.low,u=0,c=0,l=0,h=0;return l+=(h+=i*f)>>>16,c+=(l+=n*f)>>>16,l&=65535,c+=(l+=i*a)>>>16,u+=(c+=r*f)>>>16,c&=65535,u+=(c+=n*a)>>>16,c&=65535,u+=(c+=i*o)>>>16,u+=t*f+r*a+n*o+i*s,m((l&=65535)<<16|(h&=65535),(u&=65535)<<16|(c&=65535),this.unsigned)},t.mul=t.multiply,t.divide=function(e){if(d(e)||(e=y(e)),e.isZero())throw Error("division by zero");if(this.isZero())return this.unsigned?f:_;var t,r,n;if(this.unsigned){if(e.unsigned||(e=e.toUnsigned()),e.gt(this))return f;if(e.gt(this.shru(1)))return h;n=f}else{if(this.eq(j))return e.eq(u)||e.eq(g)?j:e.eq(j)?u:(t=this.shr(1).div(e).shl(1)).eq(_)?e.isNegative()?u:g:(r=this.sub(e.mul(t)),n=t.add(r.div(e)));else if(e.eq(j))return this.unsigned?f:_;if(this.isNegative())return e.isNegative()?this.neg().div(e.neg()):this.neg().div(e).neg();if(e.isNegative())return this.div(e.neg()).neg();n=_}for(r=this;r.gte(e);){t=Math.max(1,Math.floor(r.toNumber()/e.toNumber()));for(var i=Math.ceil(Math.log(t)/Math.LN2),s=i<=48?1:c(2,i-48),o=p(t),a=o.mul(e);a.isNegative()||a.gt(r);)a=(o=p(t-=s,this.unsigned)).mul(e);o.isZero()&&(o=u),n=n.add(o),r=r.sub(a)}return n},t.div=t.divide,t.modulo=function(e){return d(e)||(e=y(e)),this.sub(this.div(e).mul(e))},t.mod=t.modulo,t.not=function(){return m(~this.low,~this.high,this.unsigned)},t.and=function(e){return d(e)||(e=y(e)),m(this.low&e.low,this.high&e.high,this.unsigned)},t.or=function(e){return d(e)||(e=y(e)),m(this.low|e.low,this.high|e.high,this.unsigned)},t.xor=function(e){return d(e)||(e=y(e)),m(this.low^e.low,this.high^e.high,this.unsigned)},t.shiftLeft=function(e){return d(e)&&(e=e.toInt()),0==(e&=63)?this:e<32?m(this.low<>>32-e,this.unsigned):m(0,this.low<>>e|this.high<<32-e,this.high>>e,this.unsigned):m(this.high>>e-32,0<=this.high?0:-1,this.unsigned)},t.shr=t.shiftRight,t.shiftRightUnsigned=function(e){if(d(e)&&(e=e.toInt()),0===(e&=63))return this;var t=this.high;return e<32?m(this.low>>>e|t<<32-e,t>>>e,this.unsigned):m(32===e?t:t>>>e-32,0,this.unsigned)},t.shru=t.shiftRightUnsigned,t.toSigned=function(){return this.unsigned?m(this.low,this.high,!1):this},t.toUnsigned=function(){return this.unsigned?this:m(this.low,this.high,!0)},t.toBytes=function(e){return e?this.toBytesLE():this.toBytesBE()},t.toBytesLE=function(){var e=this.high,t=this.low;return[255&t,t>>>8&255,t>>>16&255,t>>>24&255,255&e,e>>>8&255,e>>>16&255,e>>>24&255]},t.toBytesBE=function(){var e=this.high,t=this.low;return[e>>>24&255,e>>>16&255,e>>>8&255,255&e,t>>>24&255,t>>>16&255,t>>>8&255,255&t]},n},"function"==typeof e&&"object"==typeof t&&t&&t.exports?t.exports=i():(n.dcodeIO=n.dcodeIO||{}).Long=i()},{}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/md5.js/index.js":[function(i,s,e){(function(t){"use strict";var e=i("inherits"),r=i("hash-base"),o=new Array(16);function n(){r.call(this,64),this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878}function a(e,t){return e<>>32-t}function f(e,t,r,n,i,s,o){return a(e+(t&r|~t&n)+i+s|0,o)+t|0}function u(e,t,r,n,i,s,o){return a(e+(t&n|r&~n)+i+s|0,o)+t|0}function c(e,t,r,n,i,s,o){return a(e+(t^r^n)+i+s|0,o)+t|0}function l(e,t,r,n,i,s,o){return a(e+(r^(t|~n))+i+s|0,o)+t|0}e(n,r),n.prototype._update=function(){for(var e=o,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);var r=this._a,n=this._b,i=this._c,s=this._d;n=l(n=l(n=l(n=l(n=c(n=c(n=c(n=c(n=u(n=u(n=u(n=u(n=f(n=f(n=f(n=f(n,i=f(i,s=f(s,r=f(r,n,i,s,e[0],3614090360,7),n,i,e[1],3905402710,12),r,n,e[2],606105819,17),s,r,e[3],3250441966,22),i=f(i,s=f(s,r=f(r,n,i,s,e[4],4118548399,7),n,i,e[5],1200080426,12),r,n,e[6],2821735955,17),s,r,e[7],4249261313,22),i=f(i,s=f(s,r=f(r,n,i,s,e[8],1770035416,7),n,i,e[9],2336552879,12),r,n,e[10],4294925233,17),s,r,e[11],2304563134,22),i=f(i,s=f(s,r=f(r,n,i,s,e[12],1804603682,7),n,i,e[13],4254626195,12),r,n,e[14],2792965006,17),s,r,e[15],1236535329,22),i=u(i,s=u(s,r=u(r,n,i,s,e[1],4129170786,5),n,i,e[6],3225465664,9),r,n,e[11],643717713,14),s,r,e[0],3921069994,20),i=u(i,s=u(s,r=u(r,n,i,s,e[5],3593408605,5),n,i,e[10],38016083,9),r,n,e[15],3634488961,14),s,r,e[4],3889429448,20),i=u(i,s=u(s,r=u(r,n,i,s,e[9],568446438,5),n,i,e[14],3275163606,9),r,n,e[3],4107603335,14),s,r,e[8],1163531501,20),i=u(i,s=u(s,r=u(r,n,i,s,e[13],2850285829,5),n,i,e[2],4243563512,9),r,n,e[7],1735328473,14),s,r,e[12],2368359562,20),i=c(i,s=c(s,r=c(r,n,i,s,e[5],4294588738,4),n,i,e[8],2272392833,11),r,n,e[11],1839030562,16),s,r,e[14],4259657740,23),i=c(i,s=c(s,r=c(r,n,i,s,e[1],2763975236,4),n,i,e[4],1272893353,11),r,n,e[7],4139469664,16),s,r,e[10],3200236656,23),i=c(i,s=c(s,r=c(r,n,i,s,e[13],681279174,4),n,i,e[0],3936430074,11),r,n,e[3],3572445317,16),s,r,e[6],76029189,23),i=c(i,s=c(s,r=c(r,n,i,s,e[9],3654602809,4),n,i,e[12],3873151461,11),r,n,e[15],530742520,16),s,r,e[2],3299628645,23),i=l(i,s=l(s,r=l(r,n,i,s,e[0],4096336452,6),n,i,e[7],1126891415,10),r,n,e[14],2878612391,15),s,r,e[5],4237533241,21),i=l(i,s=l(s,r=l(r,n,i,s,e[12],1700485571,6),n,i,e[3],2399980690,10),r,n,e[10],4293915773,15),s,r,e[1],2240044497,21),i=l(i,s=l(s,r=l(r,n,i,s,e[8],1873313359,6),n,i,e[15],4264355552,10),r,n,e[6],2734768916,15),s,r,e[13],1309151649,21),i=l(i,s=l(s,r=l(r,n,i,s,e[4],4149444226,6),n,i,e[11],3174756917,10),r,n,e[2],718787259,15),s,r,e[9],3951481745,21),this._a=this._a+r|0,this._b=this._b+n|0,this._c=this._c+i|0,this._d=this._d+s|0},n.prototype._digest=function(){this._block[this._blockOffset++]=128,56this.urls.length-1)return t(new Error("Tried "+(i+1)+" connections, none of which worked: "+JSON.stringify(this.urls.concat(this.url))));var o=function(e,t){return s.logFailure(n),s.connectWithFallback(r,s.urls[i],i+1,e,t)};return e&&t?this.connect(r,n).then(e).catch(function(){o(e,t)}):new Promise(function(e,t){s.connect(r).then(e).catch(function(){o(e,t)})})},n.prototype.checkConnections=function(){var i=0t.highWaterMark&&(t.highWaterMark=(m<=(r=e)?r=m:(r--,r|=r>>>1,r|=r>>>2,r|=r>>>4,r|=r>>>8,r|=r>>>16,r++),r)),e<=t.length?e:t.ended?t.length:(t.needReadable=!0,0));var r}function j(e){var t=e._readableState;t.needReadable=!1,t.emittedReadable||(w("emitReadable",t.flowing),t.emittedReadable=!0,t.sync?b.nextTick(E,e):E(e))}function E(e){w("emit readable"),e.emit("readable"),D(e)}function B(e,t){t.readingMore||(t.readingMore=!0,b.nextTick(x,e,t))}function x(e,t){for(var r=t.length;!t.reading&&!t.flowing&&!t.ended&&t.length=t.length?(r=t.decoder?t.buffer.join(""):1===t.buffer.length?t.buffer.head.data:t.buffer.concat(t.length),t.buffer.clear()):r=function(e,t,r){var n;es.length?s.length:e;if(o===s.length?i+=s:i+=s.slice(0,e),0===(e-=o)){o===s.length?(++n,r.next?t.head=r.next:t.head=t.tail=null):(t.head=r).data=s.slice(o);break}++n}return t.length-=n,i}(e,t):function(e,t){var r=u.allocUnsafe(e),n=t.head,i=1;n.data.copy(r),e-=n.data.length;for(;n=n.next;){var s=n.data,o=e>s.length?s.length:e;if(s.copy(r,r.length-e,0,o),0===(e-=o)){o===s.length?(++i,n.next?t.head=n.next:t.head=t.tail=null):(t.head=n).data=s.slice(o);break}++i}return t.length-=i,r}(e,t);return n}(e,t.buffer,t.decoder),r);var r}function S(e){var t=e._readableState;if(0=t.highWaterMark||t.ended))return w("read: emitReadable",t.length,t.ended),0===t.length&&t.ended?S(this):j(this),null;if(0===(e=v(e,t))&&t.ended)return 0===t.length&&S(this),null;var n,i=t.needReadable;return w("need readable",i),(0===t.length||t.length-e>>0),s=this.head,o=0;s;)t=s.data,r=i,n=o,t.copy(r,n),o+=s.data.length,s=s.next;return i},e}(),n&&n.inspect&&n.inspect.custom&&(t.exports.prototype[n.inspect.custom]=function(){var e=n.inspect({length:this.length});return this.constructor.name+" "+e})},{"safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js",util:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/browser-resolve/empty.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/destroy.js":[function(e,t,r){"use strict";var s=e("process-nextick-args");function o(e,t){e.emit("error",t)}t.exports={destroy:function(e,t){var r=this,n=this._readableState&&this._readableState.destroyed,i=this._writableState&&this._writableState.destroyed;return n||i?t?t(e):!e||this._writableState&&this._writableState.errorEmitted||s.nextTick(o,this,e):(this._readableState&&(this._readableState.destroyed=!0),this._writableState&&(this._writableState.destroyed=!0),this._destroy(e||null,function(e){!t&&e?(s.nextTick(o,r,e),r._writableState&&(r._writableState.errorEmitted=!0)):t&&t(e)})),this},undestroy:function(){this._readableState&&(this._readableState.destroyed=!1,this._readableState.reading=!1,this._readableState.ended=!1,this._readableState.endEmitted=!1),this._writableState&&(this._writableState.destroyed=!1,this._writableState.ended=!1,this._writableState.ending=!1,this._writableState.finished=!1,this._writableState.errorEmitted=!1)}}},{"process-nextick-args":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/process-nextick-args/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/internal/streams/stream-browser.js":[function(e,t,r){t.exports=e("events").EventEmitter},{events:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/events/events.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/passthrough.js":[function(e,t,r){t.exports=e("./readable").PassThrough},{"./readable":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/readable-browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/readable-browser.js":[function(e,t,r){(((r=t.exports=e("./lib/_stream_readable.js")).Stream=r).Readable=r).Writable=e("./lib/_stream_writable.js"),r.Duplex=e("./lib/_stream_duplex.js"),r.Transform=e("./lib/_stream_transform.js"),r.PassThrough=e("./lib/_stream_passthrough.js")},{"./lib/_stream_duplex.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_duplex.js","./lib/_stream_passthrough.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_passthrough.js","./lib/_stream_readable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_readable.js","./lib/_stream_transform.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_transform.js","./lib/_stream_writable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_writable.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/transform.js":[function(e,t,r){t.exports=e("./readable").Transform},{"./readable":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/readable-browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/writable-browser.js":[function(e,t,r){t.exports=e("./lib/_stream_writable.js")},{"./lib/_stream_writable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/lib/_stream_writable.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/ripemd160/index.js":[function(e,t,r){"use strict";var n=e("buffer").Buffer,i=e("inherits"),s=e("hash-base"),y=new Array(16),b=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13],_=[5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11],g=[11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6],w=[8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11],v=[0,1518500249,1859775393,2400959708,2840853838],j=[1352829926,1548603684,1836072691,2053994217,0];function o(){s.call(this,64),this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520}function E(e,t){return e<>>32-t}function B(e,t,r,n,i,s,o,a){return E(e+(t^r^n)+s+o|0,a)+i|0}function x(e,t,r,n,i,s,o,a){return E(e+(t&r|~t&n)+s+o|0,a)+i|0}function U(e,t,r,n,i,s,o,a){return E(e+((t|~r)^n)+s+o|0,a)+i|0}function k(e,t,r,n,i,s,o,a){return E(e+(t&n|r&~n)+s+o|0,a)+i|0}function D(e,t,r,n,i,s,o,a){return E(e+(t^(r|~n))+s+o|0,a)+i|0}i(o,s),o.prototype._update=function(){for(var e=y,t=0;t<16;++t)e[t]=this._block.readInt32LE(4*t);for(var r=0|this._a,n=0|this._b,i=0|this._c,s=0|this._d,o=0|this._e,a=0|this._a,f=0|this._b,u=0|this._c,c=0|this._d,l=0|this._e,h=0;h<80;h+=1){var d,p;p=h<16?(d=B(r,n,i,s,o,e[b[h]],v[0],g[h]),D(a,f,u,c,l,e[_[h]],j[0],w[h])):h<32?(d=x(r,n,i,s,o,e[b[h]],v[1],g[h]),k(a,f,u,c,l,e[_[h]],j[1],w[h])):h<48?(d=U(r,n,i,s,o,e[b[h]],v[2],g[h]),U(a,f,u,c,l,e[_[h]],j[2],w[h])):h<64?(d=k(r,n,i,s,o,e[b[h]],v[3],g[h]),x(a,f,u,c,l,e[_[h]],j[3],w[h])):(d=D(r,n,i,s,o,e[b[h]],v[4],g[h]),B(a,f,u,c,l,e[_[h]],j[4],w[h])),r=o,o=s,s=E(i,10),i=n,n=d,a=l,l=c,c=E(u,10),u=f,f=p}var m=this._b+i+c|0;this._b=this._c+s+l|0,this._c=this._d+o+a|0,this._d=this._e+r+f|0,this._e=this._a+n+u|0,this._a=m},o.prototype._digest=function(){this._block[this._blockOffset++]=128,56=this._finalSize&&(this._update(this._block),this._block.fill(0));var r=8*this._len;if(r<=4294967295)this._block.writeUInt32BE(r,this._blockSize-4);else{var n=(4294967295&r)>>>0,i=(r-n)/4294967296;this._block.writeUInt32BE(i,this._blockSize-8),this._block.writeUInt32BE(n,this._blockSize-4)}this._update(this._block);var s=this._hash();return e?s.toString(e):s},n.prototype._update=function(){throw new Error("_update must be implemented by subclass")},t.exports=n},{"safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/index.js":[function(e,t,r){(r=t.exports=function(e){e=e.toLowerCase();var t=r[e];if(!t)throw new Error(e+" is not supported (we accept pull requests)");return new t}).sha=e("./sha"),r.sha1=e("./sha1"),r.sha224=e("./sha224"),r.sha256=e("./sha256"),r.sha384=e("./sha384"),r.sha512=e("./sha512")},{"./sha":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha.js","./sha1":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha1.js","./sha224":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha224.js","./sha256":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha256.js","./sha384":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha384.js","./sha512":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha512.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha.js":[function(e,t,r){var n=e("inherits"),i=e("./hash"),s=e("safe-buffer").Buffer,b=[1518500249,1859775393,-1894007588,-899497514],o=new Array(80);function a(){this.init(),this._w=o,i.call(this,64,56)}n(a,i),a.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this},a.prototype._update=function(e){for(var t,r,n,i,s,o,a=this._w,f=0|this._a,u=0|this._b,c=0|this._c,l=0|this._d,h=0|this._e,d=0;d<16;++d)a[d]=e.readInt32BE(4*d);for(;d<80;++d)a[d]=a[d-3]^a[d-8]^a[d-14]^a[d-16];for(var p=0;p<80;++p){var m=~~(p/20),y=0|((o=f)<<5|o>>>27)+(n=u,i=c,s=l,0===(r=m)?n&i|~n&s:2===r?n&i|n&s|i&s:n^i^s)+h+a[p]+b[m];h=l,l=c,c=(t=u)<<30|t>>>2,u=f,f=y}this._a=f+this._a|0,this._b=u+this._b|0,this._c=c+this._c|0,this._d=l+this._d|0,this._e=h+this._e|0},a.prototype._hash=function(){var e=s.allocUnsafe(20);return e.writeInt32BE(0|this._a,0),e.writeInt32BE(0|this._b,4),e.writeInt32BE(0|this._c,8),e.writeInt32BE(0|this._d,12),e.writeInt32BE(0|this._e,16),e},t.exports=a},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js",inherits:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha1.js":[function(e,t,r){var n=e("inherits"),i=e("./hash"),s=e("safe-buffer").Buffer,_=[1518500249,1859775393,-1894007588,-899497514],o=new Array(80);function a(){this.init(),this._w=o,i.call(this,64,56)}n(a,i),a.prototype.init=function(){return this._a=1732584193,this._b=4023233417,this._c=2562383102,this._d=271733878,this._e=3285377520,this},a.prototype._update=function(e){for(var t,r,n,i,s,o,a,f=this._w,u=0|this._a,c=0|this._b,l=0|this._c,h=0|this._d,d=0|this._e,p=0;p<16;++p)f[p]=e.readInt32BE(4*p);for(;p<80;++p)f[p]=(t=f[p-3]^f[p-8]^f[p-14]^f[p-16])<<1|t>>>31;for(var m=0;m<80;++m){var y=~~(m/20),b=0|((a=u)<<5|a>>>27)+(i=c,s=l,o=h,0===(n=y)?i&s|~i&o:2===n?i&s|i&o|s&o:i^s^o)+d+f[m]+_[y];d=h,h=l,l=(r=c)<<30|r>>>2,c=u,u=b}this._a=u+this._a|0,this._b=c+this._b|0,this._c=l+this._c|0,this._d=h+this._d|0,this._e=d+this._e|0},a.prototype._hash=function(){var e=s.allocUnsafe(20);return e.writeInt32BE(0|this._a,0),e.writeInt32BE(0|this._b,4),e.writeInt32BE(0|this._c,8),e.writeInt32BE(0|this._d,12),e.writeInt32BE(0|this._e,16),e},t.exports=a},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js",inherits:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha224.js":[function(e,t,r){var n=e("inherits"),i=e("./sha256"),s=e("./hash"),o=e("safe-buffer").Buffer,a=new Array(64);function f(){this.init(),this._w=a,s.call(this,64,56)}n(f,i),f.prototype.init=function(){return this._a=3238371032,this._b=914150663,this._c=812702999,this._d=4144912697,this._e=4290775857,this._f=1750603025,this._g=1694076839,this._h=3204075428,this},f.prototype._hash=function(){var e=o.allocUnsafe(28);return e.writeInt32BE(this._a,0),e.writeInt32BE(this._b,4),e.writeInt32BE(this._c,8),e.writeInt32BE(this._d,12),e.writeInt32BE(this._e,16),e.writeInt32BE(this._f,20),e.writeInt32BE(this._g,24),e},t.exports=f},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js","./sha256":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha256.js",inherits:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha256.js":[function(e,t,r){var n=e("inherits"),i=e("./hash"),s=e("safe-buffer").Buffer,v=[1116352408,1899447441,3049323471,3921009573,961987163,1508970993,2453635748,2870763221,3624381080,310598401,607225278,1426881987,1925078388,2162078206,2614888103,3248222580,3835390401,4022224774,264347078,604807628,770255983,1249150122,1555081692,1996064986,2554220882,2821834349,2952996808,3210313671,3336571891,3584528711,113926993,338241895,666307205,773529912,1294757372,1396182291,1695183700,1986661051,2177026350,2456956037,2730485921,2820302411,3259730800,3345764771,3516065817,3600352804,4094571909,275423344,430227734,506948616,659060556,883997877,958139571,1322822218,1537002063,1747873779,1955562222,2024104815,2227730452,2361852424,2428436474,2756734187,3204031479,3329325298],o=new Array(64);function a(){this.init(),this._w=o,i.call(this,64,56)}n(a,i),a.prototype.init=function(){return this._a=1779033703,this._b=3144134277,this._c=1013904242,this._d=2773480762,this._e=1359893119,this._f=2600822924,this._g=528734635,this._h=1541459225,this},a.prototype._update=function(e){for(var t,r,n,i,s,o,a,f=this._w,u=0|this._a,c=0|this._b,l=0|this._c,h=0|this._d,d=0|this._e,p=0|this._f,m=0|this._g,y=0|this._h,b=0;b<16;++b)f[b]=e.readInt32BE(4*b);for(;b<64;++b)f[b]=0|(((r=f[b-2])>>>17|r<<15)^(r>>>19|r<<13)^r>>>10)+f[b-7]+(((t=f[b-15])>>>7|t<<25)^(t>>>18|t<<14)^t>>>3)+f[b-16];for(var _=0;_<64;++_){var g=y+(((a=d)>>>6|a<<26)^(a>>>11|a<<21)^(a>>>25|a<<7))+((o=m)^d&(p^o))+v[_]+f[_]|0,w=0|(((s=u)>>>2|s<<30)^(s>>>13|s<<19)^(s>>>22|s<<10))+((n=u)&(i=c)|l&(n|i));y=m,m=p,p=d,d=h+g|0,h=l,l=c,c=u,u=g+w|0}this._a=u+this._a|0,this._b=c+this._b|0,this._c=l+this._c|0,this._d=h+this._d|0,this._e=d+this._e|0,this._f=p+this._f|0,this._g=m+this._g|0,this._h=y+this._h|0},a.prototype._hash=function(){var e=s.allocUnsafe(32);return e.writeInt32BE(this._a,0),e.writeInt32BE(this._b,4),e.writeInt32BE(this._c,8),e.writeInt32BE(this._d,12),e.writeInt32BE(this._e,16),e.writeInt32BE(this._f,20),e.writeInt32BE(this._g,24),e.writeInt32BE(this._h,28),e},t.exports=a},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js",inherits:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha384.js":[function(e,t,r){var n=e("inherits"),i=e("./sha512"),s=e("./hash"),o=e("safe-buffer").Buffer,a=new Array(160);function f(){this.init(),this._w=a,s.call(this,128,112)}n(f,i),f.prototype.init=function(){return this._ah=3418070365,this._bh=1654270250,this._ch=2438529370,this._dh=355462360,this._eh=1731405415,this._fh=2394180231,this._gh=3675008525,this._hh=1203062813,this._al=3238371032,this._bl=914150663,this._cl=812702999,this._dl=4144912697,this._el=4290775857,this._fl=1750603025,this._gl=1694076839,this._hl=3204075428,this},f.prototype._hash=function(){var n=o.allocUnsafe(48);function e(e,t,r){n.writeInt32BE(e,r),n.writeInt32BE(t,r+4)}return e(this._ah,this._al,0),e(this._bh,this._bl,8),e(this._ch,this._cl,16),e(this._dh,this._dl,24),e(this._eh,this._el,32),e(this._fh,this._fl,40),n},t.exports=f},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js","./sha512":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha512.js",inherits:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/sha512.js":[function(e,t,r){var n=e("inherits"),i=e("./hash"),s=e("safe-buffer").Buffer,ee=[1116352408,3609767458,1899447441,602891725,3049323471,3964484399,3921009573,2173295548,961987163,4081628472,1508970993,3053834265,2453635748,2937671579,2870763221,3664609560,3624381080,2734883394,310598401,1164996542,607225278,1323610764,1426881987,3590304994,1925078388,4068182383,2162078206,991336113,2614888103,633803317,3248222580,3479774868,3835390401,2666613458,4022224774,944711139,264347078,2341262773,604807628,2007800933,770255983,1495990901,1249150122,1856431235,1555081692,3175218132,1996064986,2198950837,2554220882,3999719339,2821834349,766784016,2952996808,2566594879,3210313671,3203337956,3336571891,1034457026,3584528711,2466948901,113926993,3758326383,338241895,168717936,666307205,1188179964,773529912,1546045734,1294757372,1522805485,1396182291,2643833823,1695183700,2343527390,1986661051,1014477480,2177026350,1206759142,2456956037,344077627,2730485921,1290863460,2820302411,3158454273,3259730800,3505952657,3345764771,106217008,3516065817,3606008344,3600352804,1432725776,4094571909,1467031594,275423344,851169720,430227734,3100823752,506948616,1363258195,659060556,3750685593,883997877,3785050280,958139571,3318307427,1322822218,3812723403,1537002063,2003034995,1747873779,3602036899,1955562222,1575990012,2024104815,1125592928,2227730452,2716904306,2361852424,442776044,2428436474,593698344,2756734187,3733110249,3204031479,2999351573,3329325298,3815920427,3391569614,3928383900,3515267271,566280711,3940187606,3454069534,4118630271,4000239992,116418474,1914138554,174292421,2731055270,289380356,3203993006,460393269,320620315,685471733,587496836,852142971,1086792851,1017036298,365543100,1126000580,2618297676,1288033470,3409855158,1501505948,4234509866,1607167915,987167468,1816402316,1246189591],o=new Array(160);function a(){this.init(),this._w=o,i.call(this,128,112)}function te(e,t,r){return r^e&(t^r)}function re(e,t,r){return e&t|r&(e|t)}function ne(e,t){return(e>>>28|t<<4)^(t>>>2|e<<30)^(t>>>7|e<<25)}function ie(e,t){return(e>>>14|t<<18)^(e>>>18|t<<14)^(t>>>9|e<<23)}function se(e,t){return e>>>0>>0?1:0}n(a,i),a.prototype.init=function(){return this._ah=1779033703,this._bh=3144134277,this._ch=1013904242,this._dh=2773480762,this._eh=1359893119,this._fh=2600822924,this._gh=528734635,this._hh=1541459225,this._al=4089235720,this._bl=2227873595,this._cl=4271175723,this._dl=1595750129,this._el=2917565137,this._fl=725511199,this._gl=4215389547,this._hl=327033209,this},a.prototype._update=function(e){for(var t,r,n,i,s,o,a,f,u=this._w,c=0|this._ah,l=0|this._bh,h=0|this._ch,d=0|this._dh,p=0|this._eh,m=0|this._fh,y=0|this._gh,b=0|this._hh,_=0|this._al,g=0|this._bl,w=0|this._cl,v=0|this._dl,j=0|this._el,E=0|this._fl,B=0|this._gl,x=0|this._hl,U=0;U<32;U+=2)u[U]=e.readInt32BE(4*U),u[U+1]=e.readInt32BE(4*U+4);for(;U<160;U+=2){var k=u[U-30],D=u[U-30+1],T=((a=k)>>>1|(f=D)<<31)^(a>>>8|f<<24)^a>>>7,S=((s=D)>>>1|(o=k)<<31)^(s>>>8|o<<24)^(s>>>7|o<<25);k=u[U-4],D=u[U-4+1];var I=((n=k)>>>19|(i=D)<<13)^(i>>>29|n<<3)^n>>>6,A=((t=D)>>>19|(r=k)<<13)^(r>>>29|t<<3)^(t>>>6|r<<26),O=u[U-14],L=u[U-14+1],C=u[U-32],R=u[U-32+1],P=S+L|0,q=T+O+se(P,S)|0;q=(q=q+I+se(P=P+A|0,A)|0)+C+se(P=P+R|0,R)|0,u[U]=q,u[U+1]=P}for(var M=0;M<160;M+=2){q=u[M],P=u[M+1];var z=re(c,l,h),N=re(_,g,w),F=ne(c,_),K=ne(_,c),H=ie(p,j),V=ie(j,p),Y=ee[M],W=ee[M+1],Z=te(p,m,y),G=te(j,E,B),J=x+V|0,X=b+H+se(J,x)|0;X=(X=(X=X+Z+se(J=J+G|0,G)|0)+Y+se(J=J+W|0,W)|0)+q+se(J=J+P|0,P)|0;var $=K+N|0,Q=F+z+se($,K)|0;b=y,x=B,y=m,B=E,m=p,E=j,p=d+X+se(j=v+J|0,v)|0,d=h,v=w,h=l,w=g,l=c,g=_,c=X+Q+se(_=J+$|0,J)|0}this._al=this._al+_|0,this._bl=this._bl+g|0,this._cl=this._cl+w|0,this._dl=this._dl+v|0,this._el=this._el+j|0,this._fl=this._fl+E|0,this._gl=this._gl+B|0,this._hl=this._hl+x|0,this._ah=this._ah+c+se(this._al,_)|0,this._bh=this._bh+l+se(this._bl,g)|0,this._ch=this._ch+h+se(this._cl,w)|0,this._dh=this._dh+d+se(this._dl,v)|0,this._eh=this._eh+p+se(this._el,j)|0,this._fh=this._fh+m+se(this._fl,E)|0,this._gh=this._gh+y+se(this._gl,B)|0,this._hh=this._hh+b+se(this._hl,x)|0},a.prototype._hash=function(){var n=s.allocUnsafe(64);function e(e,t,r){n.writeInt32BE(e,r),n.writeInt32BE(t,r+4)}return e(this._ah,this._al,0),e(this._bh,this._bl,8),e(this._ch,this._cl,16),e(this._dh,this._dl,24),e(this._eh,this._el,32),e(this._fh,this._fl,40),e(this._gh,this._gl,48),e(this._hh,this._hl,56),n},t.exports=a},{"./hash":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/sha.js/hash.js",inherits:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","safe-buffer":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/safe-buffer/index.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/stream-browserify/index.js":[function(e,t,r){t.exports=n;var c=e("events").EventEmitter;function n(){c.call(this)}e("inherits")(n,c),n.Readable=e("readable-stream/readable.js"),n.Writable=e("readable-stream/writable.js"),n.Duplex=e("readable-stream/duplex.js"),n.Transform=e("readable-stream/transform.js"),n.PassThrough=e("readable-stream/passthrough.js"),(n.Stream=n).prototype.pipe=function(t,e){var r=this;function n(e){t.writable&&!1===t.write(e)&&r.pause&&r.pause()}function i(){r.readable&&r.resume&&r.resume()}r.on("data",n),t.on("drain",i),t._isStdio||e&&!1===e.end||(r.on("end",o),r.on("close",a));var s=!1;function o(){s||(s=!0,t.end())}function a(){s||(s=!0,"function"==typeof t.destroy&&t.destroy())}function f(e){if(u(),0===c.listenerCount(this,"error"))throw e}function u(){r.removeListener("data",n),t.removeListener("drain",i),r.removeListener("end",o),r.removeListener("close",a),r.removeListener("error",f),t.removeListener("error",f),r.removeListener("end",u),r.removeListener("close",u),t.removeListener("close",u)}return r.on("error",f),t.on("error",f),r.on("end",u),r.on("close",u),t.on("close",u),t.emit("pipe",r),t}},{events:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/events/events.js",inherits:"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/inherits/inherits_browser.js","readable-stream/duplex.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/duplex-browser.js","readable-stream/passthrough.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/passthrough.js","readable-stream/readable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/readable-browser.js","readable-stream/transform.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/transform.js","readable-stream/writable.js":"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/readable-stream/writable-browser.js"}],"/Users/mseaward/Documents/code/peerplaysjs-lib/node_modules/string_decoder/lib/string_decoder.js":[function(e,t,r){"use strict";var n=e("safe-buffer").Buffer,i=n.isEncoding||function(e){switch((e=""+e)&&e.toLowerCase()){case"hex":case"utf8":case"utf-8":case"ascii":case"binary":case"base64":case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":case"raw":return!0;default:return!1}};function s(e){var t;switch(this.encoding=function(e){var t=function(e){if(!e)return"utf8";for(var t;;)switch(e){case"utf8":case"utf-8":return"utf8";case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return"utf16le";case"latin1":case"binary":return"latin1";case"base64":case"ascii":case"hex":return e;default:if(t)return;e=(""+e).toLowerCase(),t=!0}}(e);if("string"!=typeof t&&(n.isEncoding===i||!i(e)))throw new Error("Unknown encoding: "+e);return t||e}(e),this.encoding){case"utf16le":this.text=f,this.end=u,t=4;break;case"utf8":this.fillLast=a,t=4;break;case"base64":this.text=c,this.end=l,t=3;break;default:return this.write=h,void(this.end=d)}this.lastNeed=0,this.lastTotal=0,this.lastChar=n.allocUnsafe(t)}function o(e){return e<=127?0:e>>5==6?2:e>>4==14?3:e>>3==30?4:e>>6==2?-1:-2}function a(e){var t=this.lastTotal-this.lastNeed,r=function(e,t,r){if(128!=(192&t[0]))return e.lastNeed=0,"�";if(1 Map(state_string => Set of tournament ids)) + // it maintains a map of tournaments a given account is allowed to participate + // in (open-registration tournaments or tournaments they are whitelisted for). + // the null account maps to all tournaments + // accounts and states will not be tracked until their first access + this.tournament_ids_by_state = Immutable.Map().set(null, new Immutable.Map()); + + // registered_tournaments_details_by_player is a map of + // Map(registered_account_id => Set of tournament details objects) + // it only tracks tournaments which the account has registered to play in + this.registered_tournament_ids_by_player = Immutable.Map(); + + this.last_tournament_id = undefined; + + this.store_initialized = false; + } + }, { + key: "resetCache", + value: function resetCache() { + this.subscribed = false; + this.clearCache(); + this.head_block_time_string = null; + this.init().then(function (result) { + console.log("resetCache init success"); + }).catch(function (err) { + console.log("resetCache init error:", err); + }); + } + }, { + key: "setDispatchFrequency", + value: function setDispatchFrequency(freq) { + this.dispatchFrequency = freq; + } + }, { + key: "init", + value: function init() { + var _this = this; + + var reconnectCounter = 0; + var _init = function _init(resolve, reject) { + var db_api = Apis.instance().db_api(); + if (!db_api) { + return reject(new Error("Api not found, please initialize the api instance before calling the ChainStore")); + } + return db_api.exec("get_objects", [["2.1.0"]]).then(function (optional_objects) { + //if(DEBUG) console.log('... optional_objects',optional_objects ? optional_objects[0].id : null) + for (var i = 0; i < optional_objects.length; i++) { + var optional_object = optional_objects[i]; + if (optional_object) { + + _this._updateObject(optional_object, true); + + var head_time = new Date(optional_object.time + "+00:00").getTime(); + _this.head_block_time_string = optional_object.time; + _this.chain_time_offset.push(new Date().getTime() - _this.timeStringToDate(optional_object.time).getTime()); + var now = new Date().getTime(); + var delta = (now - head_time) / 1000; + var start = Date.parse('Sep 1, 2015'); + var progress_delta = head_time - start; + _this.progress = progress_delta / (now - start); + + if (delta < 60) { + Apis.instance().db_api().exec("set_subscribe_callback", [_this.onUpdate.bind(_this), true]).then(function (v) { + console.log("synced and subscribed, chainstore ready"); + _this.subscribed = true; + _this.fetchRecentOperations(); + resolve(); + }).catch(function (error) { + reject(error); + console.log("Error: ", error); + }); + } else { + console.log("not yet synced, retrying in 1s"); + reconnectCounter++; + if (reconnectCounter > 10) { + throw new Error("ChainStore sync error, please check your system clock"); + } + setTimeout(_init.bind(_this, resolve, reject), 1000); + } + } else { + setTimeout(_init.bind(_this, resolve, reject), 1000); + } + } + }).catch(function (error) { + // in the event of an error clear the pending state for id + console.log('!!! Chain API error', error); + _this.objects_by_id = _this.objects_by_id.delete("2.1.0"); + reject(error); + }); + }; + + return new Promise(function (resolve, reject) { + return _init(resolve, reject); + }); + } + }, { + key: "onUpdate", + value: function onUpdate(updated_objects) /// map from account id to objects + { + emitter.emit('heartbeat'); + // updated_objects is the parameter list, it should always be exactly + // one element long. + // The single parameter to this callback function is a vector of variants, where + // each entry indicates one changed object. + // If the entry is an object id, it means the object has been removed. If it + // is an full object, then the object is either newly-created or changed. + for (var a = 0; a < updated_objects.length; ++a) { + for (var i = 0; i < updated_objects[a].length; ++i) { + var obj = updated_objects[a][i]; + + if (ChainValidation.is_object_id(obj)) { + /// the object was removed + // Cancelled limit order, emit event for MarketStore to update it's state + if (obj.search(order_prefix) == 0) { + var old_obj = this.objects_by_id.get(obj); + if (!old_obj) { + return; + } + emitter.emit('cancel-order', old_obj.get("id")); + var account = this.objects_by_id.get(old_obj.get("seller")); + if (account && account.has("orders")) { + var limit_orders = account.get("orders"); + if (account.get("orders").has(obj)) { + account = account.set("orders", limit_orders.delete(obj)); + this.objects_by_id = this.objects_by_id.set(account.get("id"), account); + } + } + } + + // Update nested call_order inside account object + if (obj.search(call_order_prefix) == 0) { + + var _old_obj = this.objects_by_id.get(obj); + if (!_old_obj) { + return; + } + emitter.emit('close-call', _old_obj.get("id")); + var _account = this.objects_by_id.get(_old_obj.get("borrower")); + if (_account && _account.has("call_orders")) { + var call_orders = _account.get("call_orders"); + if (_account.get("call_orders").has(obj)) { + _account = _account.set("call_orders", call_orders.delete(obj)); + this.objects_by_id = this.objects_by_id.set(_account.get("id"), _account); + } + } + } + + // Remove the object + this.objects_by_id = this.objects_by_id.set(obj, null); + } else this._updateObject(obj, false); + } + } + this.notifySubscribers(); + } + }, { + key: "notifySubscribers", + value: function notifySubscribers() { + var _this2 = this; + + // Dispatch at most only once every x milliseconds + if (!this.dispatched) { + this.dispatched = true; + setTimeout(function () { + _this2.dispatched = false; + _this2.subscribers.forEach(function (callback) { + callback(); + }); + }, this.dispatchFrequency); + } + } + + /** + * Add a callback that will be called anytime any object in the cache is updated + */ + + }, { + key: "subscribe", + value: function subscribe(callback) { + if (this.subscribers.has(callback)) console.error("Subscribe callback already exists", callback); + this.subscribers.add(callback); + } + + /** + * Remove a callback that was previously added via subscribe + */ + + }, { + key: "unsubscribe", + value: function unsubscribe(callback) { + if (!this.subscribers.has(callback)) console.error("Unsubscribe callback does not exists", callback); + this.subscribers.delete(callback); + } + + /** Clear an object from the cache to force it to be fetched again. This may + * be useful if a query failed the first time and the wallet has reason to believe + * it may succeede the second time. + */ + + }, { + key: "clearObjectCache", + value: function clearObjectCache(id) { + this.objects_by_id = this.objects_by_id.delete(id); + } + + /** + * There are three states an object id could be in: + * + * 1. undefined - returned if a query is pending + * 3. defined - return an object + * 4. null - query return null + * + */ + + }, { + key: "getObject", + value: function getObject(id) { + var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (!ChainValidation.is_object_id(id)) throw Error("argument is not an object id: " + JSON.stringify(id)); + + var result = this.objects_by_id.get(id); + if (result === undefined || force) return this.fetchObject(id, force); + if (result === true) return undefined; + + return result; + } + }, { + key: "getSimpleObjectById", + value: function getSimpleObjectById(id) { + var _this3 = this; + + return new Promise(function (success, fail) { + if (!ChainValidation.is_object_id(id)) fail("argument is not an object id: " + JSON.stringify(id)); + + var result = _this3.simple_objects_by_id.get(id); + + if (result) { + return success(result); + } + Apis.instance().db_api().exec("get_objects", [[id]]).then(function (objects) { + var object = objects[0]; + if (!object) return success(null); + _this3.simple_objects_by_id = _this3.simple_objects_by_id.set(id, object); + success(object); + }); + }); + } + + /** + * @return undefined if a query is pending + * @return null if id_or_symbol has been queired and does not exist + * @return object if the id_or_symbol exists + */ + + }, { + key: "getAsset", + value: function getAsset(id_or_symbol) { + var _this4 = this; + + if (!id_or_symbol) return null; + + if (ChainValidation.is_object_id(id_or_symbol)) { + var asset = this.getObject(id_or_symbol); + + if (asset && asset.get("bitasset") && !asset.getIn(["bitasset", "current_feed"])) { + return undefined; + } + return asset; + } + + /// TODO: verify id_or_symbol is a valid symbol name + + var asset_id = this.assets_by_symbol.get(id_or_symbol); + + if (ChainValidation.is_object_id(asset_id)) { + var _asset = this.getObject(asset_id); + + if (_asset && _asset.get("bitasset") && !_asset.getIn(["bitasset", "current_feed"])) { + return undefined; + } + return _asset; + } + + if (asset_id === null) return null; + + if (asset_id === true) return undefined; + + Apis.instance().db_api().exec("lookup_asset_symbols", [[id_or_symbol]]).then(function (asset_objects) { + // console.log( "lookup symbol ", id_or_symbol ) + if (asset_objects.length && asset_objects[0]) _this4._updateObject(asset_objects[0], true);else { + _this4.assets_by_symbol = _this4.assets_by_symbol.set(id_or_symbol, null); + _this4.notifySubscribers(); + } + }).catch(function (error) { + console.log("Error: ", error); + _this4.assets_by_symbol = _this4.assets_by_symbol.delete(id_or_symbol); + }); + + return undefined; + } + + /** + * @param the public key to find accounts that reference it + * + * @return Set of account ids that reference the given key + * @return a empty Set if no items are found + * @return undefined if the result is unknown + * + * If this method returns undefined, then it will send a request to + * the server for the current set of accounts after which the + * server will notify us of any accounts that reference these keys + */ + + }, { + key: "getAccountRefsOfKey", + value: function getAccountRefsOfKey(key) { + var _this5 = this; + + if (this.get_account_refs_of_keys_calls.has(key)) return this.account_ids_by_key.get(key);else { + this.get_account_refs_of_keys_calls = this.get_account_refs_of_keys_calls.add(key); + Apis.instance().db_api().exec("get_key_references", [[key]]).then(function (vec_account_id) { + var refs = Immutable.Set(); + vec_account_id = vec_account_id[0]; + refs = refs.withMutations(function (r) { + for (var i = 0; i < vec_account_id.length; ++i) { + r.add(vec_account_id[i]); + } + }); + _this5.account_ids_by_key = _this5.account_ids_by_key.set(key, refs); + _this5.notifySubscribers(); + }, function (error) { + _this5.account_ids_by_key = _this5.account_ids_by_key.delete(key); + _this5.get_account_refs_of_keys_calls = _this5.get_account_refs_of_keys_calls.delete(key); + }); + return undefined; + } + return undefined; + } + + /** + * @return a Set of balance ids that are claimable with the given address + * @return undefined if a query is pending and the set is not known at this time + * @return a empty Set if no items are found + * + * If this method returns undefined, then it will send a request to the server for + * the current state after which it will be subscribed to changes to this set. + */ + + }, { + key: "getBalanceObjects", + value: function getBalanceObjects(address) { + var _this6 = this; + + var current = this.balance_objects_by_address.get(address); + if (current === undefined) { + /** because balance objects are simply part of the genesis state, there is no need to worry about + * having to update them / merge them or index them in updateObject. + */ + this.balance_objects_by_address = this.balance_objects_by_address.set(address, Immutable.Set()); + Apis.instance().db_api().exec("get_balance_objects", [[address]]).then(function (balance_objects) { + var set = new Set(); + for (var i = 0; i < balance_objects.length; ++i) { + _this6._updateObject(balance_objects[i]); + set.add(balance_objects[i].id); + } + _this6.balance_objects_by_address = _this6.balance_objects_by_address.set(address, Immutable.Set(set)); + _this6.notifySubscribers(); + }, function (error) { + _this6.balance_objects_by_address = _this6.balance_objects_by_address.delete(address); + }); + } + return this.balance_objects_by_address.get(address); + } + + /** + * @return a list of tournament ids for upcoming tournaments + * @return an empty list if a query is pending and the set is not known at this time + * or if there are no upcoming touraments + * + * If we have not yet requested tournaments for this account, it will send a request to the server for + * the current list, after which it will be subscribed to changes to this set. + */ + + }, { + key: "getTournamentIdsInState", + value: function getTournamentIdsInState(accountId, stateString) { + var _this7 = this; + + var tournamentIdsForThisAccountAndState = undefined; + var tournamentIdsForThisAccount = this.tournament_ids_by_state.get(accountId); + if (tournamentIdsForThisAccount === undefined) { + tournamentIdsForThisAccountAndState = new Immutable.Set(); + tournamentIdsForThisAccount = new Immutable.Map().set(stateString, tournamentIdsForThisAccountAndState); + this.tournament_ids_by_state = this.tournament_ids_by_state.set(accountId, tournamentIdsForThisAccount); + } else { + tournamentIdsForThisAccountAndState = tournamentIdsForThisAccount.get(stateString); + if (tournamentIdsForThisAccountAndState !== undefined) return tournamentIdsForThisAccountAndState; + + tournamentIdsForThisAccountAndState = new Immutable.Set(); + tournamentIdsForThisAccount = tournamentIdsForThisAccount.set(stateString, tournamentIdsForThisAccountAndState); + this.tournament_ids_by_state = this.tournament_ids_by_state.set(accountId, tournamentIdsForThisAccount); + } + + Apis.instance().db_api().exec("get_tournaments_in_state", [stateString, 100]).then(function (tournaments) { + var originalTournamentIdsInState = _this7.tournament_ids_by_state.getIn([accountId, stateString]); + // call updateObject on each tournament, which will classify it + tournaments.forEach(function (tournament) { + /** + * Fix bug: we cant update tournament_ids_by_state if objects_by_id has a tournament + */ + if (!originalTournamentIdsInState.get(tournament.id)) { + _this7.clearObjectCache(tournament.id); + } + + _this7._updateObject(tournament, false); // false = don't notify on change + }); + if (_this7.tournament_ids_by_state.getIn([accountId, stateString]) != originalTournamentIdsInState) _this7.notifySubscribers(); + }); + return tournamentIdsForThisAccountAndState; + } + }, { + key: "getRegisteredTournamentIds", + value: function getRegisteredTournamentIds(accountId) { + var _this8 = this; + + var tournamentIds = this.registered_tournament_ids_by_player.get(accountId); + if (tournamentIds !== undefined) return tournamentIds; + tournamentIds = new Immutable.Set(); + this.registered_tournament_ids_by_player = this.registered_tournament_ids_by_player.set(accountId, tournamentIds); + + Apis.instance().db_api().exec("get_registered_tournaments", [accountId, 100]).then(function (tournamentIds) { + var originalTournamentIds = _this8.registered_tournament_ids_by_player.get(accountId); + var newTournamentIds = new Immutable.Set(tournamentIds); + if (!originalTournamentIds.equals(newTournamentIds)) { + _this8.registered_tournament_ids_by_player = _this8.registered_tournament_ids_by_player.set(accountId, newTournamentIds); + _this8.notifySubscribers(); + } + }); + + return tournamentIds; + } + + /** + * If there is not already a pending request to fetch this object, a new + * request will be made. + * + * @return null if the object does not exist, + * @return undefined if the object might exist but is not in cache + * @return the object if it does exist and is in our cache + */ + + }, { + key: "fetchObject", + value: function fetchObject(id) { + var _this9 = this; + + var force = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + if (typeof id !== 'string') { + var _result = []; + for (var i = 0; i < id.length; ++i) { + _result.push(this.fetchObject(id[i])); + }return _result; + } + + if (DEBUG) console.log("!!! fetchObject: ", id, this.subscribed, !this.subscribed && !force); + if (!this.subscribed && !force) return undefined; + + if (DEBUG) console.log("maybe fetch object: ", id); + if (!ChainValidation.is_object_id(id)) throw Error("argument is not an object id: " + id); + + if (id.substring(0, 4) == "1.2.") return this.fetchFullAccount(id); + + var result = this.objects_by_id.get(id); + if (result === undefined) { + // the fetch + if (DEBUG) console.log("fetching object: ", id); + this.objects_by_id = this.objects_by_id.set(id, true); + Apis.instance().db_api().exec("get_objects", [[id]]).then(function (optional_objects) { + if (DEBUG) console.log('... optional_objects', optional_objects ? optional_objects[0].id : null); + for (var _i = 0; _i < optional_objects.length; _i++) { + var optional_object = optional_objects[_i]; + if (optional_object) { + _this9._updateObject(optional_object, true); + _this9.simple_objects_by_id = _this9.simple_objects_by_id.set(id, optional_object); + } else { + _this9.objects_by_id = _this9.objects_by_id.set(id, null); + _this9.notifySubscribers(); + } + } + }).catch(function (error) { + // in the event of an error clear the pending state for id + console.log('!!! Chain API error', error); + _this9.objects_by_id = _this9.objects_by_id.delete(id); + }); + } else if (result === true) // then we are waiting a response + return undefined; + return result; // we have a response, return it + } + + /** + * @return null if no such account exists + * @return undefined if such an account may exist, and fetch the the full account if not already pending + * @return the account object if it does exist + */ + + }, { + key: "getAccount", + value: function getAccount(name_or_id) { + + if (!name_or_id) return null; + + if ((typeof name_or_id === "undefined" ? "undefined" : _typeof(name_or_id)) === 'object') { + if (name_or_id.id) return this.getAccount(name_or_id.id);else if (name_or_id.get) return this.getAccount(name_or_id.get('id'));else return undefined; + } + + if (ChainValidation.is_object_id(name_or_id)) { + var account = this.getObject(name_or_id); + if (account === null) { + return null; + } + if (account === undefined || account.get('name') === undefined) { + return this.fetchFullAccount(name_or_id); + } + return account; + } else if (ChainValidation.is_account_name(name_or_id, true)) { + var account_id = this.accounts_by_name.get(name_or_id); + if (account_id === null) return null; // already fetched and it wasn't found + if (account_id === undefined) // then no query, fetch it + return this.fetchFullAccount(name_or_id); + return this.getObject(account_id); // return it + } + //throw Error( `Argument is not an account name or id: ${name_or_id}` ) + } + + /** + * This method will attempt to lookup witness by account_id. + * If witness doesn't exist it will return null, if witness is found it will return witness object, + * if it's not fetched yet it will return undefined. + * @param account_id - account id + */ + + }, { + key: "getWitnessById", + value: function getWitnessById(account_id) { + var witness_id = this.witness_by_account_id.get(account_id); + if (witness_id === undefined) { + this.fetchWitnessByAccount(account_id); + return undefined; + } + return witness_id ? this.getObject(witness_id) : null; + } + + /** + * This method will attempt to lookup witness by account_id. + * If witness doesn't exist it will return null, if witness is found it will return witness object, + * if it's not fetched yet it will return undefined. + * @param witness_id - witness id + */ + + }, { + key: "getWitnessAccount", + value: function getWitnessAccount(witness_id) { + var _this10 = this; + + return new Promise(function (success, fail) { + var account = _this10.account_by_witness_id.get(witness_id); + + if (account) return success(account); + + _this10.getSimpleObjectById(witness_id).then(function (witness) { + _this10.getSimpleObjectById(witness.witness_account).then(function (account) { + _this10.account_by_witness_id = _this10.account_by_witness_id.set(witness_id, account); + success(account); + }); + }); + }); + } + + /** + * This method will attempt to lookup committee member by account_id. + * If committee member doesn't exist it will return null, if committee member is found it will return committee member object, + * if it's not fetched yet it will return undefined. + * @param account_id - account id + */ + + }, { + key: "getCommitteeMemberById", + value: function getCommitteeMemberById(account_id) { + var cm_id = this.committee_by_account_id.get(account_id); + if (cm_id === undefined) { + this.fetchCommitteeMemberByAccount(account_id); + return undefined; + } + return cm_id ? this.getObject(cm_id) : null; + } + + /** + * Obsolete! Please use getWitnessById + * This method will attempt to lookup the account, and then query to see whether or not there is + * a witness for this account. If the answer is known, it will return the witness_object, otherwise + * it will attempt to look it up and return null. Once the lookup has completed on_update will + * be called. + * + * @param id_or_account may either be an account_id, a witness_id, or an account_name + */ + + }, { + key: "getWitness", + value: function getWitness(id_or_account) { + var _this11 = this; + + var account = this.getAccount(id_or_account); + if (!account) return null; + var account_id = account.get('id'); + + var witness_id = this.witness_by_account_id.get(account_id); + if (witness_id === undefined) this.fetchWitnessByAccount(account_id); + return this.getObject(witness_id); + + if (ChainValidation.is_account_name(id_or_account, true) || id_or_account.substring(0, 4) == "1.2.") { + var _account2 = this.getAccount(id_or_account); + if (!_account2) { + this.lookupAccountByName(id_or_account).then(function (account) { + if (!account) return null; + + var account_id = account.get('id'); + var witness_id = _this11.witness_by_account_id.get(account_id); + if (ChainValidation.is_object_id(witness_id)) return _this11.getObject(witness_id, on_update); + + if (witness_id == undefined) _this11.fetchWitnessByAccount(account_id).then(function (witness) { + _this11.witness_by_account_id.set(account_id, witness ? witness.get('id') : null); + if (witness && on_update) on_update(); + }); + }, function (error) { + var witness_id = _this11.witness_by_account_id.set(id_or_account, null); + }); + } else { + var _account_id = _account2.get('id'); + var _witness_id = this.witness_by_account_id.get(_account_id); + if (ChainValidation.is_object_id(_witness_id)) return this.getObject(_witness_id, on_update); + + if (_witness_id == undefined) this.fetchWitnessByAccount(_account_id).then(function (witness) { + _this11.witness_by_account_id.set(_account_id, witness ? witness.get('id') : null); + if (witness && on_update) on_update(); + }); + } + return null; + } + return null; + } + + // Obsolete! Please use getCommitteeMemberById + + }, { + key: "getCommitteeMember", + value: function getCommitteeMember(id_or_account) { + var _this12 = this; + + var on_update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + if (ChainValidation.is_account_name(id_or_account, true) || id_or_account.substring(0, 4) == "1.2.") { + var account = this.getAccount(id_or_account); + + if (!account) { + this.lookupAccountByName(id_or_account).then(function (account) { + var account_id = account.get('id'); + var committee_id = _this12.committee_by_account_id.get(account_id); + if (ChainValidation.is_object_id(committee_id)) return _this12.getObject(committee_id, on_update); + + if (committee_id == undefined) { + _this12.fetchCommitteeMemberByAccount(account_id).then(function (committee) { + _this12.committee_by_account_id.set(account_id, committee ? committee.get('id') : null); + if (on_update && committee) on_update(); + }); + } + }, function (error) { + var witness_id = _this12.committee_by_account_id.set(id_or_account, null); + }); + } else { + var account_id = account.get('id'); + var committee_id = this.committee_by_account_id.get(account_id); + if (ChainValidation.is_object_id(committee_id)) return this.getObject(committee_id, on_update); + + if (committee_id == undefined) { + this.fetchCommitteeMemberByAccount(account_id).then(function (committee) { + _this12.committee_by_account_id.set(account_id, committee ? committee.get('id') : null); + if (on_update && committee) on_update(); + }); + } + } + } + return null; + } + + /** + * + * @returns a promise with a list of all witness ids. Regardless of if they have been voted in or not. + * @memberof ChainStore + */ + + }, { + key: "fetchWitnessAccounts", + value: function fetchWitnessAccounts() { + var _this13 = this; + + return new Promise(function (resolve, reject) { + Apis.instance().db_api().exec("lookup_witness_accounts", [0, 1000]).then(function (w) { + if (w) { + var witnessArr = []; + + for (var i = 0, length = w.length; i < length; i++) { + witnessArr.push(w[i][1]); // ids only + } + + _this13.witnesses = _this13.witnesses.merge(witnessArr); + _this13._updateObject(witnessArr, true); + resolve(_this13.witnesses); + } else { + resolve(null); + } + }); + }); + } + + /** + * + * @return a promise with the witness object + */ + + }, { + key: "fetchWitnessByAccount", + value: function fetchWitnessByAccount(account_id) { + var _this14 = this; + + return new Promise(function (resolve, reject) { + Apis.instance().db_api().exec("get_witness_by_account", [account_id]).then(function (optional_witness_object) { + if (optional_witness_object) { + _this14.witness_by_account_id = _this14.witness_by_account_id.set(optional_witness_object.witness_account, optional_witness_object.id); + var witness_object = _this14._updateObject(optional_witness_object, true); + resolve(witness_object); + } else { + _this14.witness_by_account_id = _this14.witness_by_account_id.set(account_id, null); + _this14.notifySubscribers(); + resolve(null); + } + }, reject); + }); + } + + /** + * + * @return a promise with the witness object + */ + + }, { + key: "fetchCommitteeMemberByAccount", + value: function fetchCommitteeMemberByAccount(account_id) { + var _this15 = this; + + return new Promise(function (resolve, reject) { + Apis.instance().db_api().exec("get_committee_member_by_account", [account_id]).then(function (optional_committee_object) { + if (optional_committee_object) { + _this15.committee_by_account_id = _this15.committee_by_account_id.set(optional_committee_object.committee_member_account, optional_committee_object.id); + var committee_object = _this15._updateObject(optional_committee_object, true); + resolve(committee_object); + } else { + _this15.committee_by_account_id = _this15.committee_by_account_id.set(account_id, null); + _this15.notifySubscribers(); + resolve(null); + } + }, reject); + }); + } + + /** + * Fetches an account and all of its associated data in a single query + * + * @param an account name or account id + * + * @return undefined if the account in question is in the process of being fetched + * @return the object if it has already been fetched + * @return null if the object has been queried and was not found + */ + + }, { + key: "fetchFullAccount", + value: function fetchFullAccount(name_or_id) { + var _this16 = this; + + if (DEBUG) console.log("Fetch full account: ", name_or_id); + + var fetch_account = false; + if (ChainValidation.is_object_id(name_or_id)) { + var current = this.objects_by_id.get(name_or_id); + fetch_account = current === undefined; + if (!fetch_account && fetch_account.get('name')) return current; + } else { + if (!ChainValidation.is_account_name(name_or_id, true)) throw Error("argument is not an account name: " + name_or_id); + + var account_id = this.accounts_by_name.get(name_or_id); + if (ChainValidation.is_object_id(account_id)) return this.getAccount(account_id); + } + + /// only fetch once every 5 seconds if it wasn't found + if (!this.fetching_get_full_accounts.has(name_or_id) || Date.now() - this.fetching_get_full_accounts.get(name_or_id) > 5000) { + this.fetching_get_full_accounts.set(name_or_id, Date.now()); + //console.log( "FETCHING FULL ACCOUNT: ", name_or_id ) + Apis.instance().db_api().exec("get_full_accounts", [[name_or_id], true]).then(function (results) { + if (results.length === 0) { + if (ChainValidation.is_object_id(name_or_id)) { + _this16.objects_by_id = _this16.objects_by_id.set(name_or_id, null); + _this16.notifySubscribers(); + } + return; + } + var full_account = results[0][1]; + if (DEBUG) console.log("full_account: ", full_account); + + var account = full_account.account, + vesting_balances = full_account.vesting_balances, + pending_dividend_payments = full_account.pending_dividend_payments, + statistics = full_account.statistics, + call_orders = full_account.call_orders, + limit_orders = full_account.limit_orders, + referrer_name = full_account.referrer_name, + registrar_name = full_account.registrar_name, + lifetime_referrer_name = full_account.lifetime_referrer_name, + votes = full_account.votes, + proposals = full_account.proposals; + + + _this16.accounts_by_name = _this16.accounts_by_name.set(account.name, account.id); + account.referrer_name = referrer_name; + account.lifetime_referrer_name = lifetime_referrer_name; + account.registrar_name = registrar_name; + account.balances = {}; + account.orders = new Immutable.Set(); + account.vesting_balances = new Immutable.Set(); + account.pending_dividend_payments = new Immutable.Set(); + account.balances = new Immutable.Map(); + account.call_orders = new Immutable.Set(); + account.proposals = new Immutable.Set(); + account.vesting_balances = account.vesting_balances.withMutations(function (set) { + vesting_balances.forEach(function (vb) { + _this16._updateObject(vb, false); + set.add(vb.id); + }); + }); + + votes.forEach(function (v) { + return _this16._updateObject(v, false); + }); + + account.balances = account.balances.withMutations(function (map) { + full_account.balances.forEach(function (b) { + _this16._updateObject(b, false); + map.set(b.asset_type, b.id); + }); + }); + + account.orders = account.orders.withMutations(function (set) { + limit_orders.forEach(function (order) { + _this16._updateObject(order, false); + set.add(order.id); + }); + }); + + account.pending_dividend_payments = account.pending_dividend_payments.withMutations(function (set) { + pending_dividend_payments.forEach(function (payments) { + _this16._updateObject(payments, false); + set.add(payments); + }); + }); + + account.call_orders = account.call_orders.withMutations(function (set) { + call_orders.forEach(function (co) { + _this16._updateObject(co, false); + set.add(co.id); + }); + }); + + account.proposals = account.proposals.withMutations(function (set) { + proposals.forEach(function (p) { + _this16._updateObject(p, false); + set.add(p.id); + }); + }); + + _this16._updateObject(statistics, false); + var updated_account = _this16._updateObject(account, false); + _this16.fetchRecentHistory(updated_account); + _this16.notifySubscribers(); + }, function (error) { + console.log("Error: ", error); + if (ChainValidation.is_object_id(name_or_id)) _this16.objects_by_id = _this16.objects_by_id.delete(name_or_id);else _this16.accounts_by_name = _this16.accounts_by_name.delete(name_or_id); + }); + } + return undefined; + } + }, { + key: "getAccountMemberStatus", + value: function getAccountMemberStatus(account) { + if (account === undefined) return undefined; + if (account === null) return "unknown"; + if (account.get('lifetime_referrer') == account.get('id')) return "lifetime"; + var exp = new Date(account.get('membership_expiration_date')).getTime(); + var now = new Date().getTime(); + if (exp < now) return "basic"; + return "annual"; + } + }, { + key: "getAccountBalance", + value: function getAccountBalance(account, asset_type) { + var balances = account.get('balances'); + if (!balances) return 0; + + var balance_obj_id = balances.get(asset_type); + if (balance_obj_id) { + var bal_obj = this.objects_by_id.get(balance_obj_id); + if (bal_obj) return bal_obj.get('balance'); + } + return 0; + } + + /** + * There are two ways to extend the account history, add new more + * recent history, and extend historic hstory. This method will fetch + * the most recent account history and prepend it to the list of + * historic operations. + * + * @param account immutable account object + * @return a promise with the account history + */ + + }, { + key: "fetchRecentHistory", + value: function fetchRecentHistory(account) { + var _this17 = this; + + var limit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100; + + // console.log( "get account history: ", account ) + /// TODO: make sure we do not submit a query if there is already one + /// in flight... + var account_id = account; + if (!ChainValidation.is_object_id(account_id) && account.toJS) account_id = account.get('id'); + + if (!ChainValidation.is_object_id(account_id)) return; + + account = this.objects_by_id.get(account_id); + if (!account) return; + + var pending_request = this.account_history_requests.get(account_id); + if (pending_request) { + pending_request.requests++; + return pending_request.promise; + } else pending_request = { requests: 0 }; + + var most_recent = "1." + op_history + ".0"; + var history = account.get('history'); + + if (history && history.size) most_recent = history.first().get('id'); + + /// starting at 0 means start at NOW, set this to something other than 0 + /// to skip recent transactions and fetch the tail + var start = "1." + op_history + ".0"; + + pending_request.promise = new Promise(function (resolve, reject) { + Apis.instance().history_api().exec("get_account_history", [account_id, most_recent, limit, start]).then(function (operations) { + var current_account = _this17.objects_by_id.get(account_id); + var current_history = current_account.get('history'); + if (!current_history) current_history = Immutable.List(); + var updated_history = Immutable.fromJS(operations); + updated_history = updated_history.withMutations(function (list) { + for (var i = 0; i < current_history.size; ++i) { + list.push(current_history.get(i)); + } + }); + var updated_account = current_account.set('history', updated_history); + _this17.objects_by_id = _this17.objects_by_id.set(account_id, updated_account); + + //if( current_history != updated_history ) + // this._notifyAccountSubscribers( account_id ) + + var pending_request = _this17.account_history_requests.get(account_id); + _this17.account_history_requests.delete(account_id); + if (pending_request.requests > 0) { + // it looks like some more history may have come in while we were + // waiting on the result, lets fetch anything new before we resolve + // this query. + _this17.fetchRecentHistory(updated_account, limit).then(resolve, reject); + } else resolve(updated_account); + }); // end then + }); + + this.account_history_requests.set(account_id, pending_request); + return pending_request.promise; + } + + //_notifyAccountSubscribers( account_id ) + //{ + // let sub = this.subscriptions_by_account.get( account_id ) + // let acnt = this.objects_by_id.get(account_id) + // if( !sub ) return + // for( let item of sub.subscriptions ) + // item( acnt ) + //} + + /** + * Callback that receives notification of objects that have been + * added, remove, or changed and are relevant to account_id + * + * This method updates or removes objects from the main index and + * then updates the account object with relevant meta-info depending + * upon the type of account + */ + // _updateAccount( account_id, payload ) + // { + // let updates = payload[0] + + // for( let i = 0; i < updates.length; ++i ) + // { + // let update = updates[i] + // if( typeof update == 'string' ) + // { + // let old_obj = this._removeObject( update ) + + // if( update.search( order_prefix ) == 0 ) + // { + // acnt = acnt.setIn( ['orders'], set => set.delete(update) ) + // } + // else if( update.search( vesting_balance_prefix ) == 0 ) + // { + // acnt = acnt.setIn( ['vesting_balances'], set => set.delete(update) ) + // } + // } + // else + // { + // let updated_obj = this._updateObject( update ) + // if( update.id.search( balance_prefix ) == 0 ) + // { + // if( update.owner == account_id ) + // acnt = acnt.setIn( ['balances'], map => map.set(update.asset_type,update.id) ) + // } + // else if( update.id.search( order_prefix ) == 0 ) + // { + // if( update.owner == account_id ) + // acnt = acnt.setIn( ['orders'], set => set.add(update.id) ) + // } + // else if( update.id.search( vesting_balance_prefix ) == 0 ) + // { + // if( update.owner == account_id ) + // acnt = acnt.setIn( ['vesting_balances'], set => set.add(update.id) ) + // } + + // this.objects_by_id = this.objects_by_id.set( acnt.id, acnt ) + // } + // } + // this.fetchRecentHistory( acnt ) + // } + + /** + * Updates the object in place by only merging the set + * properties of object. + * + * This method will create an immutable object with the given ID if + * it does not already exist. + * + * This is a "private" method called when data is received from the + * server and should not be used by others. + * + * @pre object.id must be a valid object ID + * @return an Immutable constructed from object and deep merged with the current state + */ + + }, { + key: "_updateObject", + value: function _updateObject(object, notify_subscribers) { + var emit = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; + + + if (!("id" in object)) { + console.log("object with no id:", object); + if ("balance" in object && "owner" in object && "settlement_date" in object) { + // Settle order object + emitter.emit("settle-order-update", object); + } + return; + } + // if (!(object.id.split(".")[0] == 2) && !(object.id.split(".")[1] == 6)) { + // console.log( "update: ", object ) + // } + + // DYNAMIC GLOBAL OBJECT + if (object.id == "2.1.0") { + object.participation = 100 * (BigInteger(object.recent_slots_filled).bitCount() / 128.0); + this.head_block_time_string = object.time; + this.chain_time_offset.push(Date.now() - this.timeStringToDate(object.time).getTime()); + if (this.chain_time_offset.length > 10) this.chain_time_offset.shift(); // remove first + this.fetchRecentOperations(object.head_block_number); + } + + var current = this.objects_by_id.get(object.id, undefined); + if (current === undefined || current === true) current = Immutable.Map(); + var prior = current; + if (current === undefined || current === true) this.objects_by_id = this.objects_by_id.set(object.id, current = Immutable.fromJS(object));else this.objects_by_id = this.objects_by_id.set(object.id, current = current.mergeDeep(Immutable.fromJS(object))); + + // BALANCE OBJECT + if (object.id.substring(0, balance_prefix.length) == balance_prefix) { + var owner = this.objects_by_id.get(object.owner); + if (owner === undefined || owner === null) { + return; + /* This prevents the full account from being looked up later + owner = {id:object.owner, balances:{ } } + owner.balances[object.asset_type] = object.id + owner = Immutable.fromJS( owner ) + */ + } else { + var balances = owner.get("balances"); + if (!balances) owner = owner.set("balances", Immutable.Map()); + owner = owner.setIn(['balances', object.asset_type], object.id); + } + this.objects_by_id = this.objects_by_id.set(object.owner, owner); + } + // ACCOUNT STATS OBJECT + else if (object.id.substring(0, account_stats_prefix.length) == account_stats_prefix) { + // console.log( "HISTORY CHANGED" ) + var prior_most_recent_op = prior ? prior.get('most_recent_op') : "2.9.0"; + + if (prior_most_recent_op != object.most_recent_op) { + this.fetchRecentHistory(object.owner); + } + } + // WITNESS OBJECT + else if (object.id.substring(0, witness_prefix.length) == witness_prefix) { + this.witness_by_account_id.set(object.witness_account, object.id); + this.objects_by_vote_id.set(object.vote_id, object.id); + } + // COMMITTEE MEMBER OBJECT + else if (object.id.substring(0, committee_prefix.length) == committee_prefix) { + this.committee_by_account_id.set(object.committee_member_account, object.id); + this.objects_by_vote_id.set(object.vote_id, object.id); + } + // ACCOUNT OBJECT + else if (object.id.substring(0, account_prefix.length) == account_prefix) { + current = current.set('active', Immutable.fromJS(object.active)); + current = current.set('owner', Immutable.fromJS(object.owner)); + current = current.set('options', Immutable.fromJS(object.options)); + current = current.set('pending_dividend_payments', Immutable.fromJS(object.pending_dividend_payments)); + current = current.set('whitelisting_accounts', Immutable.fromJS(object.whitelisting_accounts)); + current = current.set('blacklisting_accounts', Immutable.fromJS(object.blacklisting_accounts)); + current = current.set('whitelisted_accounts', Immutable.fromJS(object.whitelisted_accounts)); + current = current.set('blacklisted_accounts', Immutable.fromJS(object.blacklisted_accounts)); + this.objects_by_id = this.objects_by_id.set(object.id, current); + this.accounts_by_name = this.accounts_by_name.set(object.name, object.id); + } + // ASSET OBJECT + else if (object.id.substring(0, asset_prefix.length) == asset_prefix) { + this.assets_by_symbol = this.assets_by_symbol.set(object.symbol, object.id); + var dynamic = current.get('dynamic'); + if (!dynamic) { + var dad = this.getObject(object.dynamic_asset_data_id, true); + if (!dad) dad = Immutable.Map(); + if (!dad.get('asset_id')) { + dad = dad.set('asset_id', object.id); + } + this.objects_by_id = this.objects_by_id.set(object.dynamic_asset_data_id, dad); + + current = current.set('dynamic', dad); + this.objects_by_id = this.objects_by_id.set(object.id, current); + } + + var bitasset = current.get('bitasset'); + if (!bitasset && object.bitasset_data_id) { + var bad = this.getObject(object.bitasset_data_id, true); + if (!bad) bad = Immutable.Map(); + + if (!bad.get('asset_id')) { + bad = bad.set('asset_id', object.id); + } + this.objects_by_id = this.objects_by_id.set(object.bitasset_data_id, bad); + + current = current.set('bitasset', bad); + this.objects_by_id = this.objects_by_id.set(object.id, current); + } + } + // ASSET DYNAMIC DATA OBJECT + else if (object.id.substring(0, asset_dynamic_data_prefix.length) == asset_dynamic_data_prefix) { + // let asset_id = asset_prefix + object.id.substring( asset_dynamic_data_prefix.length ) + var asset_id = current.get("asset_id"); + if (asset_id) { + var asset_obj = this.getObject(asset_id); + if (asset_obj && asset_obj.set) { + asset_obj = asset_obj.set('dynamic', current); + this.objects_by_id = this.objects_by_id.set(asset_id, asset_obj); + } + } + } + // WORKER OBJECT + else if (object.id.substring(0, worker_prefix.length) == worker_prefix) { + this.objects_by_vote_id.set(object.vote_for, object.id); + this.objects_by_vote_id.set(object.vote_against, object.id); + } + // BITASSET DATA OBJECT + else if (object.id.substring(0, bitasset_data_prefix.length) == bitasset_data_prefix) { + var _asset_id = current.get("asset_id"); + if (_asset_id) { + var asset = this.getObject(_asset_id); + if (asset) { + asset = asset.set("bitasset", current); + emitter.emit('bitasset-update', asset); + this.objects_by_id = this.objects_by_id.set(_asset_id, asset); + } + } + } + // CALL ORDER OBJECT + else if (object.id.substring(0, call_order_prefix.length) == call_order_prefix) { + // Update nested call_orders inside account object + if (emit) { + emitter.emit("call-order-update", object); + } + + var account = this.objects_by_id.get(object.borrower); + if (account && account.has("call_orders")) { + var call_orders = account.get("call_orders"); + if (!call_orders.has(object.id)) { + account = account.set("call_orders", call_orders.add(object.id)); + this.objects_by_id = this.objects_by_id.set(account.get("id"), account); + } + } + } + // LIMIT ORDER OBJECT + else if (object.id.substring(0, order_prefix.length) == order_prefix) { + var _account3 = this.objects_by_id.get(object.seller); + if (_account3 && _account3.has("orders")) { + var limit_orders = _account3.get("orders"); + if (!limit_orders.has(object.id)) { + _account3 = _account3.set("orders", limit_orders.add(object.id)); + this.objects_by_id = this.objects_by_id.set(_account3.get("id"), _account3); + } + } + } + // PROPOSAL OBJECT + else if (object.id.substring(0, proposal_prefix.length) == proposal_prefix) { + this.addProposalData(object.required_active_approvals, object.id); + this.addProposalData(object.required_owner_approvals, object.id); + } + // TOURNAMENT OBJECT + else if (object.id.substring(0, tournament_prefix.length) == tournament_prefix) { + var priorState = prior.get("state"); + var newState = current.get("state"); + + if (priorState !== newState) { + this.tournament_ids_by_state = this.tournament_ids_by_state.map(function (stateMap, accountId) { + return stateMap.map(function (tournamentIdSet, stateString) { + if (stateString === priorState) return tournamentIdSet.remove(object.id);else if (stateString === newState && (accountId === null || current.getIn(["options", "whitelist"]).isEmpty() || current.getIn(["options", "whitelist"]).includes(accountId))) return tournamentIdSet.add(object.id);else return tournamentIdSet; + }); + }); + } + + if (this.last_tournament_id !== undefined) { + this.setLastTournamentId(current.get('id')); + } + } else if (object.id.substring(0, tournament_details_prefix.length) == tournament_details_prefix) { + var priorRegisteredPlayers = prior.get("registered_players"); + var newRegisteredPlayers = current.get("registered_players"); + if (priorRegisteredPlayers != newRegisteredPlayers) this.registered_tournament_ids_by_player = this.registered_tournament_ids_by_player.map(function (tournamentIdsSet, accountId) { + if (newRegisteredPlayers.includes(accountId)) return tournamentIdsSet.add(current.get("tournament_id"));else return tournamentIdsSet; + // currently, you can't un-register for a tournament, so we don't have + // to deal with removing from a list + }); + } + + if (notify_subscribers) this.notifySubscribers(); + + return current; + } + }, { + key: "setLastTournamentId", + value: function setLastTournamentId(current_tournament_id) { + if (current_tournament_id === null) { + if (!this.last_tournament_id) { + this.last_tournament_id = current_tournament_id; + } + } else { + var current_tournament_id_short = parseFloat(current_tournament_id.substring(tournament_prefix.length)), + last_tournament_id_short = this.last_tournament_id ? parseFloat(this.last_tournament_id.substring(tournament_prefix.length)) : -1; + + if (current_tournament_id_short > last_tournament_id_short) { + this.last_tournament_id = current_tournament_id; + } + } + } + }, { + key: "getTournaments", + value: function getTournaments(last_tournament_id) { + var _this18 = this; + + var limit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 5; + var start_tournament_id = arguments[2]; + + + return Apis.instance().db_api().exec("get_tournaments", [last_tournament_id, limit, start_tournament_id]).then(function (tournaments) { + var list = Immutable.List(); + + _this18.setLastTournamentId(null); + + if (tournaments && tournaments.length) { + list = list.withMutations(function (l) { + tournaments.forEach(function (tournament) { + + if (!_this18.objects_by_id.has(tournament.id)) { + _this18._updateObject(tournament, false); + } + + l.unshift(_this18.objects_by_id.get(tournament.id)); + }); + }); + } + + return list; + }); + } + }, { + key: "getLastTournamentId", + value: function getLastTournamentId() { + var _this19 = this; + + return new Promise(function (resolve, reject) { + if (_this19.last_tournament_id === undefined) { + + Apis.instance().db_api().exec("get_tournaments", [tournament_prefix + '0', 1, tournament_prefix + '0']).then(function (tournaments) { + + _this19.setLastTournamentId(null); + + if (tournaments && tournaments.length) { + + tournaments.forEach(function (tournament) { + _this19._updateObject(tournament, false); + }); + } + + resolve(_this19.last_tournament_id); + }); + } else { + + resolve(_this19.last_tournament_id); + } + }); + } + }, { + key: "getObjectsByVoteIds", + value: function getObjectsByVoteIds(vote_ids) { + var _this20 = this; + + var result = []; + var missing = []; + for (var i = 0; i < vote_ids.length; ++i) { + var obj = this.objects_by_vote_id.get(vote_ids[i]); + if (obj) result.push(this.getObject(obj));else { + result.push(null); + missing.push(vote_ids[i]); + } + } + + if (missing.length) { + // we may need to fetch some objects + Apis.instance().db_api().exec("lookup_vote_ids", [missing]).then(function (vote_obj_array) { + console.log("missing ===========> ", missing); + console.log("vote objects ===========> ", vote_obj_array); + for (var _i2 = 0; _i2 < vote_obj_array.length; ++_i2) { + if (vote_obj_array[_i2]) { + _this20._updateObject(vote_obj_array[_i2]); + } + } + }, function (error) { + return console.log("Error looking up vote ids: ", error); + }); + } + return result; + } + }, { + key: "getObjectByVoteID", + value: function getObjectByVoteID(vote_id) { + var obj_id = this.objects_by_vote_id.get(vote_id); + if (obj_id) return this.getObject(obj_id); + return undefined; + } + }, { + key: "getHeadBlockDate", + value: function getHeadBlockDate() { + return this.timeStringToDate(this.head_block_time_string); + } + }, { + key: "getEstimatedChainTimeOffset", + value: function getEstimatedChainTimeOffset() { + if (this.chain_time_offset.length === 0) return 0; + // Immutable is fast, sorts numbers correctly, and leaves the original unmodified + // This will fix itself if the user changes their clock + var median_offset = Immutable.List(this.chain_time_offset).sort().get(Math.floor((this.chain_time_offset.length - 1) / 2)); + // console.log("median_offset", median_offset) + return median_offset; + } + }, { + key: "addProposalData", + value: function addProposalData(approvals, objectId) { + var _this21 = this; + + approvals.forEach(function (id) { + var impactedAccount = _this21.objects_by_id.get(id); + if (impactedAccount) { + var proposals = impactedAccount.get("proposals"); + + if (!proposals.includes(objectId)) { + proposals = proposals.add(objectId); + impactedAccount = impactedAccount.set("proposals", proposals); + _this21._updateObject(impactedAccount.toJS(), false); + } + } + }); + } + }, { + key: "timeStringToDate", + value: function timeStringToDate(time_string) { + if (!time_string) return new Date("1970-01-01T00:00:00.000Z"); + if (!/Z$/.test(time_string)) //does not end in Z + // https://github.com/cryptonomex/graphene/issues/368 + time_string = time_string + "Z"; + return new Date(time_string); + } + }, { + key: "__getBlocksForScan", + value: function __getBlocksForScan(lastBlock) { + var _this22 = this; + + var db_api = Apis.instance().db_api(); + return new Promise(function (success, fail) { + + var scanToBlock = _this22.last_processed_block; + if (lastBlock) return success({ lastBlock: lastBlock, scanToBlock: scanToBlock }); + + db_api.exec("get_dynamic_global_properties", []).then(function (globalProperties) { + lastBlock = _this22.last_processed_block = globalProperties['head_block_number']; + scanToBlock = globalProperties['head_block_number'] - 2000; + scanToBlock = scanToBlock < 0 ? 1 : scanToBlock; + return success({ lastBlock: lastBlock, scanToBlock: scanToBlock }); + }); + }); + } + }, { + key: "__bindBlock", + value: function __bindBlock(lastBlock, scanToBlock, isInit) { + var _this23 = this; + + var db_api = Apis.instance().db_api(); + return new Promise(function (success, fail) { + db_api.exec("get_block", [lastBlock]).then(function (block) { + block.id = lastBlock; + if (typeof block.timestamp === "string") block.timestamp += "+00:00"; + block.timestamp = new Date(block.timestamp); + _this23.getWitnessAccount(block.witness).then(function (witness) { + block.witness_account_name = witness.name; + + if (!_this23.recent_blocks_by_id.get(lastBlock)) { + + _this23.recent_blocks_by_id = _this23.recent_blocks_by_id.set(lastBlock, block); + + if (_this23.last_processed_block < lastBlock) _this23.last_processed_block = lastBlock; + + if (!isInit) { + _this23.recent_blocks = _this23.recent_blocks.unshift(block); + if (_this23.recent_blocks.size > block_stack_size) { + _this23.recent_blocks = _this23.recent_blocks.pop(); + } + } else if (_this23.recent_blocks.size < block_stack_size) { + _this23.recent_blocks = _this23.recent_blocks.push(block); + } + + block.transactions.forEach(function (tx) { + return tx.operations.forEach(function (op) { + op[1].block_id = lastBlock; + op[1].created_at = block.timestamp; + if (!isInit) { + _this23.recent_operations = _this23.recent_operations.unshift(op); + } else { + if (_this23.recent_operations.size < operations_stack_size) { + _this23.recent_operations = _this23.recent_operations.push(op); + } + if (_this23.recent_operations.size >= operations_stack_size && _this23.recent_blocks.size >= block_stack_size) { + scanToBlock = lastBlock; + } + } + if (_this23.recent_operations.size > operations_stack_size) { + _this23.recent_operations = _this23.recent_operations.pop(); + } + }); + }); + } + lastBlock--; + if (lastBlock <= scanToBlock) { + return success(); + } + _this23.__bindBlock(lastBlock, scanToBlock, isInit).then(function () { + return success(); + }); + }); + }); + }); + } + }, { + key: "fetchRecentOperations", + value: function fetchRecentOperations() { + var _this24 = this; + + var lastBlock = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null; + + if (lastBlock && !this.last_processed_block) return; + var isInit = !lastBlock; + + this.__getBlocksForScan(lastBlock).then(function (_ref) { + var lastBlock = _ref.lastBlock, + scanToBlock = _ref.scanToBlock; + + _this24.__bindBlock(lastBlock, scanToBlock, isInit).then(function () { + if (isInit) { + _this24.store_initialized = true; + } + }); + }); + } + }, { + key: "getRecentBlocks", + value: function getRecentBlocks() { + return this.recent_blocks; + } + }, { + key: "getRecentOperations", + value: function getRecentOperations() { + if (!this.store_initialized) return Immutable.List(); + return this.recent_operations; + } + }]); + + return ChainStore; +}(); + +var chain_store = new ChainStore(); + +function FetchChainObjects(method, object_ids, timeout) { + var get_object = method.bind(chain_store); + + return new Promise(function (resolve, reject) { + var timeout_handle = null; + + function onUpdate() { + var not_subscribed_yet = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + + var res = object_ids.map(function (id) { + return get_object(id); + }); + if (res.findIndex(function (o) { + return o === undefined; + }) === -1) { + if (timeout_handle) clearTimeout(timeout_handle); + if (!not_subscribed_yet) chain_store.unsubscribe(onUpdate); + resolve(res); + return true; + } + return false; + } + + var resolved = onUpdate(true); + if (!resolved) chain_store.subscribe(onUpdate); + + if (timeout && !resolved) timeout_handle = setTimeout(function () { + chain_store.unsubscribe(onUpdate); + reject("timeout"); + }, timeout); + }); +} + +chain_store.FetchChainObjects = FetchChainObjects; + +function FetchChain(methodName, objectIds) { + var timeout = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1900; + + + var method = chain_store[methodName]; + if (!method) throw new Error("ChainStore does not have method " + methodName); + + var arrayIn = Array.isArray(objectIds); + if (!arrayIn) objectIds = [objectIds]; + + return chain_store.FetchChainObjects(method, Immutable.List(objectIds), timeout).then(function (res) { + return arrayIn ? res : res.get(0); + }); +} + +chain_store.FetchChain = FetchChain; + +module.exports = chain_store; \ No newline at end of file diff --git a/dist/chain/src/ChainTypes.js b/dist/chain/src/ChainTypes.js new file mode 100644 index 0000000..1a6ffa0 --- /dev/null +++ b/dist/chain/src/ChainTypes.js @@ -0,0 +1,116 @@ +"use strict"; + +var ChainTypes = {}; + +ChainTypes.reserved_spaces = { + relative_protocol_ids: 0, + protocol_ids: 1, + implementation_ids: 2 +}; + +ChainTypes.object_type = { + "null": 0, + base: 1, + account: 2, + asset: 3, + force_settlement: 4, + committee_member: 5, + witness: 6, + limit_order: 7, + call_order: 8, + custom: 9, + proposal: 10, + operation_history: 11, + withdraw_permission: 12, + vesting_balance: 13, + worker: 14, + balance: 15, + tournament: 16, + tournament_details: 17, + match_object_type: 18, + game: 19 +}; + +ChainTypes.impl_object_type = { + global_property: 0, + dynamic_global_property: 1, + index_meta: 2, + asset_dynamic_data: 3, + asset_bitasset_data: 4, + account_balance: 5, + account_statistics: 6, + transaction: 7, + block_summary: 8, + account_transaction_history: 9, + blinded_balance: 10, + chain_property: 11, + witness_schedule: 12, + budget_record: 13, + special_authority: 14, + buyback: 15, + fba_accumulator: 16, + asset_dividend_data: 17, + pending_dividend_payout_balance_for_holder: 18, + distributed_dividend_balance_data: 19 +}; + +ChainTypes.vote_type = { + committee: 0, + witness: 1, + worker: 2 +}; + +ChainTypes.operations = { + transfer: 0, + limit_order_create: 1, + limit_order_cancel: 2, + call_order_update: 3, + fill_order: 4, + account_create: 5, + account_update: 6, + account_whitelist: 7, + account_upgrade: 8, + account_transfer: 9, + asset_create: 10, + asset_update: 11, + asset_update_bitasset: 12, + asset_update_feed_producers: 13, + asset_issue: 14, + asset_reserve: 15, + asset_fund_fee_pool: 16, + asset_settle: 17, + asset_global_settle: 18, + asset_publish_feed: 19, + witness_create: 20, + witness_update: 21, + proposal_create: 22, + proposal_update: 23, + proposal_delete: 24, + withdraw_permission_create: 25, + withdraw_permission_update: 26, + withdraw_permission_claim: 27, + withdraw_permission_delete: 28, + committee_member_create: 29, + committee_member_update: 30, + committee_member_update_global_parameters: 31, + vesting_balance_create: 32, + vesting_balance_withdraw: 33, + worker_create: 34, + custom: 35, + assert: 36, + balance_claim: 37, + override_transfer: 38, + transfer_to_blind: 39, + blind_transfer: 40, + transfer_from_blind: 41, + asset_settle_cancel: 42, + asset_claim_fees: 43, + fba_distribute_operation: 44, + tournament_create: 45, + tournament_join: 46, + game_move: 47, + asset_update_dividend: 48, + asset_dividend_distribution: 49 +}; + +module.exports = ChainTypes; \ No newline at end of file diff --git a/dist/chain/src/ChainValidation.js b/dist/chain/src/ChainValidation.js new file mode 100644 index 0000000..eeb4d04 --- /dev/null +++ b/dist/chain/src/ChainValidation.js @@ -0,0 +1,144 @@ +'use strict'; + +/** + Account names may contain one or more names separated by a dot. + Each name needs to start with a letter and may contain + numbers, or well placed dashes. + @see is_valid_name graphene/libraries/chain/protocol/account.cpp +*/ +var id_regex = /\b\d+\.\d+\.(\d+)\b/; + +var chainValidation = { + is_account_name: function is_account_name(value) { + var allow_too_short = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + var i, label, len, length, ref; + + if (this.is_empty(value)) { + return false; + } + + length = value.length; + + if (!allow_too_short && length < 3 || length > 63) { + return false; + } + + ref = value.split('.'); + + for (i = 0, len = ref.length; i < len; i++) { + + label = ref[i]; + + if (!(/^[a-z][a-z0-9-]*$/.test(label) && !/--/.test(label) && /[a-z0-9]$/.test(label))) { + return false; + } + } + return true; + }, + + is_object_id: function is_object_id(obj_id) { + if ('string' != typeof obj_id) return false; + + var match = id_regex.exec(obj_id); + return match !== null && obj_id.split(".").length === 3; + }, + + is_empty: function is_empty(value) { + return value == null || value.length === 0; + }, + + is_account_name_error: function is_account_name_error(value, allow_too_short) { + var i, label, len, length, ref, suffix; + if (allow_too_short == null) { + allow_too_short = false; + } + suffix = "Account name should "; + if (this.is_empty(value)) { + return suffix + "not be empty."; + } + length = value.length; + if (!allow_too_short && length < 3) { + return suffix + "be longer."; + } + if (length > 63) { + return suffix + "be shorter."; + } + if (/\./.test(value)) { + suffix = "Each account segment should "; + } + ref = value.split('.'); + for (i = 0, len = ref.length; i < len; i++) { + label = ref[i]; + if (!/^[~a-z]/.test(label)) { + return suffix + "start with a letter."; + } + if (!/^[~a-z0-9-]*$/.test(label)) { + return suffix + "have only letters, digits, or dashes."; + } + if (/--/.test(label)) { + return suffix + "have only one dash in a row."; + } + if (!/[a-z0-9]$/.test(label)) { + return suffix + "end with a letter or digit."; + } + if (!(label.length >= 3)) { + return suffix + "be longer"; + } + } + return null; + }, + + is_cheap_name: function is_cheap_name(account_name) { + return (/[0-9-]/.test(account_name) || !/[aeiouy]/.test(account_name) + ); + }, + + is_empty_user_input: function is_empty_user_input(value) { + if (this.is_empty(value)) { + return true; + } + if ((value + "").trim() === "") { + return true; + } + return false; + }, + + required: function required(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + throw new Error("value required for " + field_name + ": " + value); + } + return value; + }, + + /** @see is_valid_symbol graphene/libraries/chain/protocol/asset_ops.cpp */ + is_valid_symbol_error: function is_valid_symbol_error(value) { + var suffix = "Asset name should "; + if (this.is_empty(value)) { + return suffix + "not be empty."; + } + if (value.split('.').length > 2) { + return suffix + "have only one dot."; + } + if (value.length < 3) { + return suffix + "be longer."; + } + if (value.length > 16) { + return suffix + "be shorter."; + } + if (!/^[A-Z]/.test(value)) { + return suffix + "start with a letter"; + } + if (!/[A-Z]$/.test(value)) { + return suffix + "end with a letter"; + } + if (/^[A-Z0-9\.]$/.test(value)) { + return suffix + "contain only letters numbers and perhaps a dot."; + } + return null; + } +}; + +module.exports = chainValidation; \ No newline at end of file diff --git a/dist/chain/src/EmitterInstance.js b/dist/chain/src/EmitterInstance.js new file mode 100644 index 0000000..9b03216 --- /dev/null +++ b/dist/chain/src/EmitterInstance.js @@ -0,0 +1,14 @@ +"use strict"; + +var ee = require("event-emitter"); + +var _emitter; + +module.exports = { + emitter: function emitter() { + if (!_emitter) { + _emitter = ee({}); + } + return _emitter; + } +}; \ No newline at end of file diff --git a/dist/chain/src/GameMoves.js b/dist/chain/src/GameMoves.js new file mode 100644 index 0000000..4c5cd1c --- /dev/null +++ b/dist/chain/src/GameMoves.js @@ -0,0 +1,113 @@ +"use strict"; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var assert = require("assert"); + +var _require = require("../../ecc"), + Signature = _require.Signature, + PublicKey = _require.PublicKey, + hash = _require.hash; + +var _require2 = require("../../serializer"), + Serializer = _require2.Serializer, + types = _require2.types; + +var _require3 = require('peerplaysjs-ws'), + Apis = _require3.Apis, + ChainConfig = _require3.ChainConfig; + +var ChainTypes = require('./ChainTypes'); +var head_block_time_string = void 0; +var ByteBuffer = require('bytebuffer'); +var secureRandom = require("secure-random"); + +var uint8 = types.uint8, + uint16 = types.uint16, + uint32 = types.uint32, + int64 = types.int64, + uint64 = types.uint64, + string = types.string, + bytes = types.bytes, + bool = types.bool, + array = types.array, + fixed_array = types.fixed_array, + protocol_id_type = types.protocol_id_type, + object_id_type = types.object_id_type, + vote_id = types.vote_id, + future_extensions = types.future_extensions, + static_variant = types.static_variant, + map = types.map, + set = types.set, + public_key = types.public_key, + address = types.address, + time_point_sec = types.time_point_sec, + optional = types.optional, + variant = types.variant, + variant_object = types.variant_object, + enumeration = types.enumeration, + sha256 = types.sha256; + + +var rock_paper_scissors_gesture = enumeration(["rock", "paper", "scissors", "spock", "lizard"]); + +var rock_paper_scissors_throw = new Serializer("rock_paper_scissors_throw", { nonce1: uint64, + nonce2: uint64, + gesture: rock_paper_scissors_gesture }); + +var rock_paper_scissors_throw_commit = new Serializer("rock_paper_scissors_throw_commit", { nonce1: uint64, + throw_hash: sha256 }); + +var rock_paper_scissors_throw_reveal = new Serializer("rock_paper_scissors_throw_reveal", { nonce2: uint64, + gesture: rock_paper_scissors_gesture }); + +var GameMoves = function () { + function GameMoves() { + _classCallCheck(this, GameMoves); + } + + _createClass(GameMoves, [{ + key: "createCommitAndRevealMoveOperations", + value: function createCommitAndRevealMoveOperations(move_type) { + var nonce1 = ByteBuffer.wrap(secureRandom.randomArray(8)).readUint64(); + var nonce2 = ByteBuffer.wrap(secureRandom.randomArray(8)).readUint64(); + + var throw_object = rock_paper_scissors_throw.fromObject({ + nonce1: nonce1, + nonce2: nonce2, + gesture: move_type + }); + var throw_object_reconstructed = rock_paper_scissors_throw.toObject(throw_object); + //console.log("Nonce1: %o, Nonce2: %o", nonce1, nonce2); + //console.log("As object: %O, as JS: %O", throw_object, throw_object_reconstructed); + var throw_buffer = rock_paper_scissors_throw.toBuffer(throw_object); + //console.log("As hex: %O", rock_paper_scissors_throw.toHex(throw_object)); + var throw_hash = hash.sha256(throw_buffer); + //console.log("Hash is : %O", throw_hash); + + var commit_move_operation_object = rock_paper_scissors_throw_commit.fromObject({ + nonce1: nonce1, + throw_hash: throw_hash + }); + var reveal_move_operation_object = rock_paper_scissors_throw_reveal.fromObject({ + nonce2: nonce2, + gesture: move_type + }); + + //console.log("Commit hex is %O, reveal hex is %O", rock_paper_scissors_throw_commit.toHex(commit_move_operation_object), rock_paper_scissors_throw_reveal.toHex(reveal_move_operation_object)); + + var commit_move_operation = rock_paper_scissors_throw_commit.toObject(commit_move_operation_object); + var reveal_move_operation = rock_paper_scissors_throw_reveal.toObject(reveal_move_operation_object); + //console.log("As JS, they are %O, %O", commit_move_operation, reveal_move_operation); + + + return [commit_move_operation, reveal_move_operation]; + } + }]); + + return GameMoves; +}(); + +module.exports = GameMoves; \ No newline at end of file diff --git a/dist/chain/src/NumberUtils.js b/dist/chain/src/NumberUtils.js new file mode 100644 index 0000000..bd772ee --- /dev/null +++ b/dist/chain/src/NumberUtils.js @@ -0,0 +1,44 @@ +"use strict"; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var assert = require("assert"); + +/** + Convert 12.34 with a precision of 3 into 12340 + + @arg {number|string} number - Use strings for large numbers. This may contain one decimal but no sign + @arg {number} precision - number of implied decimal places (usually causes right zero padding) + @return {string} - +*/ +module.exports = { + toImpliedDecimal: function toImpliedDecimal(number, precision) { + + if (typeof number === "number") { + assert(number <= 9007199254740991, "overflow"); + number = "" + number; + } else if (number.toString) number = number.toString(); + + assert(typeof number === "string", "number should be an actual number or string: " + (typeof number === "undefined" ? "undefined" : _typeof(number))); + number = number.trim(); + assert(/^[0-9]*\.?[0-9]*$/.test(number), "Invalid decimal number " + number); + + var _number$split = number.split("."), + _number$split2 = _slicedToArray(_number$split, 2), + _number$split2$ = _number$split2[0], + whole = _number$split2$ === undefined ? "" : _number$split2$, + _number$split2$2 = _number$split2[1], + decimal = _number$split2$2 === undefined ? "" : _number$split2$2; + + var padding = precision - decimal.length; + assert(padding >= 0, "Too many decimal digits in " + number + " to create an implied decimal of " + precision); + + for (var i = 0; i < padding; i++) { + decimal += "0"; + }while (whole.charAt(0) === "0") { + whole = whole.substring(1); + }return whole + decimal; + } +}; \ No newline at end of file diff --git a/dist/chain/src/ObjectId.js b/dist/chain/src/ObjectId.js new file mode 100644 index 0000000..86ff3a2 --- /dev/null +++ b/dist/chain/src/ObjectId.js @@ -0,0 +1,71 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var _require = require('bytebuffer'), + Long = _require.Long; + +var v = require('../../serializer/src/SerializerValidation'); + +var DB_MAX_INSTANCE_ID = Long.fromNumber(Math.pow(2, 48) - 1); + +var ObjectId = function () { + function ObjectId(space, type, instance) { + _classCallCheck(this, ObjectId); + + this.space = space; + this.type = type; + this.instance = instance; + var instance_string = this.instance.toString(); + var _ObjectId = this.space + '.' + this.type + '.' + instance_string; + if (!v.is_digits(instance_string)) { + throw new ('Invalid object id ' + _ObjectId)(); + } + } + + _createClass(ObjectId, [{ + key: 'toLong', + value: function toLong() { + return Long.fromNumber(this.space).shiftLeft(56).or(Long.fromNumber(this.type).shiftLeft(48).or(this.instance)); + } + }, { + key: 'appendByteBuffer', + value: function appendByteBuffer(b) { + return b.writeUint64(this.toLong()); + } + }, { + key: 'toString', + value: function toString() { + return this.space + '.' + this.type + '.' + this.instance.toString(); + } + }], [{ + key: 'fromString', + value: function fromString(value) { + if (value.space !== undefined && value.type !== undefined && value.instance !== undefined) { + return value; + } + + var params = v.require_match(/^([0-9]+)\.([0-9]+)\.([0-9]+)$/, v.required(value, "ObjectId"), "ObjectId"); + return new ObjectId(parseInt(params[1]), parseInt(params[2]), Long.fromString(params[3])); + } + }, { + key: 'fromLong', + value: function fromLong(long) { + var space = long.shiftRight(56).toInt(); + var type = long.shiftRight(48).toInt() & 0x00ff; + var instance = long.and(DB_MAX_INSTANCE_ID); + return new ObjectId(space, type, instance); + } + }, { + key: 'fromByteBuffer', + value: function fromByteBuffer(b) { + return ObjectId.fromLong(b.readUint64()); + } + }]); + + return ObjectId; +}(); + +module.exports = ObjectId; \ No newline at end of file diff --git a/dist/chain/src/TransactionBuilder.js b/dist/chain/src/TransactionBuilder.js new file mode 100644 index 0000000..8057fcc --- /dev/null +++ b/dist/chain/src/TransactionBuilder.js @@ -0,0 +1,591 @@ +"use strict"; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var assert = require("assert"); + +var _require = require("../../ecc"), + Signature = _require.Signature, + PublicKey = _require.PublicKey, + hash = _require.hash; + +var _require2 = require("../../serializer"), + ops = _require2.ops; + +var _require3 = require('peerplaysjs-ws'), + Apis = _require3.Apis, + ChainConfig = _require3.ChainConfig; + +var ChainTypes = require('./ChainTypes'); +var head_block_time_string; + +var TransactionBuilder = function () { + function TransactionBuilder() { + _classCallCheck(this, TransactionBuilder); + + this.ref_block_num = 0; + this.ref_block_prefix = 0; + this.expiration = 0; + this.operations = []; + this.signatures = []; + this.signer_private_keys = []; + + // semi-private method bindings + this._broadcast = _broadcast.bind(this); + } + + /** + @arg {string} name - like "transfer" + @arg {object} operation - JSON matchching the operation's format + */ + + + _createClass(TransactionBuilder, [{ + key: "add_type_operation", + value: function add_type_operation(name, operation) { + this.add_operation(this.get_type_operation(name, operation)); + return; + } + + /** + This does it all: set fees, finalize, sign, and broadcast (if wanted). + @arg {ConfidentialWallet} cwallet - must be unlocked, used to gather signing keys + @arg {array} [signer_pubkeys = null] - Optional ["GPHAbc9Def0...", ...]. These are additional signing keys. Some balance claims require propritary address formats, the witness node can't tell us which ones are needed so they must be passed in. If the witness node can figure out a signing key (mostly all other transactions), it should not be passed in here. + @arg {boolean} [broadcast = false] + */ + + }, { + key: "process_transaction", + value: function process_transaction(cwallet) { + var _this = this; + + var signer_pubkeys = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + var broadcast = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + + var wallet_object = cwallet.wallet.wallet_object; + if (Apis.instance().chain_id !== wallet_object.get("chain_id")) return Promise.reject("Mismatched chain_id; expecting " + wallet_object.get("chain_id") + ", but got " + Apis.instance().chain_id); + + return this.set_required_fees().then(function () { + var signer_pubkeys_added = {}; + if (signer_pubkeys) { + + // Balance claims are by address, only the private + // key holder can know about these additional + // potential keys. + var pubkeys = cwallet.getPubkeys_having_PrivateKey(signer_pubkeys); + if (!pubkeys.length) throw new Error("Missing signing key"); + + var _iteratorNormalCompletion = true; + var _didIteratorError = false; + var _iteratorError = undefined; + + try { + for (var _iterator = pubkeys[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { + var pubkey_string = _step.value; + + var private_key = cwallet.getPrivateKey(pubkey_string); + _this.add_signer(private_key, pubkey_string); + signer_pubkeys_added[pubkey_string] = true; + } + } catch (err) { + _didIteratorError = true; + _iteratorError = err; + } finally { + try { + if (!_iteratorNormalCompletion && _iterator.return) { + _iterator.return(); + } + } finally { + if (_didIteratorError) { + throw _iteratorError; + } + } + } + } + + return _this.get_potential_signatures().then(function (_ref) { + var pubkeys = _ref.pubkeys, + addys = _ref.addys; + + var my_pubkeys = cwallet.getPubkeys_having_PrivateKey(pubkeys, addys); + + //{//Testing only, don't send All public keys! + // var pubkeys_all = PrivateKeyStore.getPubkeys() // All public keys + // this.get_required_signatures(pubkeys_all).then( required_pubkey_strings => + // console.log('get_required_signatures all\t',required_pubkey_strings.sort(), pubkeys_all)) + // this.get_required_signatures(my_pubkeys).then( required_pubkey_strings => + // console.log('get_required_signatures normal\t',required_pubkey_strings.sort(), pubkeys)) + //} + + return _this.get_required_signatures(my_pubkeys).then(function (required_pubkeys) { + var _iteratorNormalCompletion2 = true; + var _didIteratorError2 = false; + var _iteratorError2 = undefined; + + try { + for (var _iterator2 = required_pubkeys[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) { + var _pubkey_string = _step2.value; + + if (signer_pubkeys_added[_pubkey_string]) continue; + var private_key = cwallet.getPrivateKey(_pubkey_string); + if (!private_key) + // This should not happen, get_required_signatures will only + // returned keys from my_pubkeys + throw new Error("Missing signing key for " + _pubkey_string); + _this.add_signer(private_key, _pubkey_string); + } + } catch (err) { + _didIteratorError2 = true; + _iteratorError2 = err; + } finally { + try { + if (!_iteratorNormalCompletion2 && _iterator2.return) { + _iterator2.return(); + } + } finally { + if (_didIteratorError2) { + throw _iteratorError2; + } + } + } + }); + }).then(function () { + return broadcast ? _this.broadcast() : _this.serialize(); + }); + }); + } + + /** Typically this is called automatically just prior to signing. Once finalized this transaction can not be changed. */ + + }, { + key: "finalize", + value: function finalize() { + var _this2 = this; + + return new Promise(function (resolve, reject) { + + if (_this2.tr_buffer) { + throw new Error("already finalized"); + } + + resolve(Apis.instance().db_api().exec("get_objects", [["2.1.0"]]).then(function (r) { + head_block_time_string = r[0].time; + if (_this2.expiration === 0) _this2.expiration = base_expiration_sec() + ChainConfig.expire_in_secs; + _this2.ref_block_num = r[0].head_block_number & 0xFFFF; + _this2.ref_block_prefix = new Buffer(r[0].head_block_id, 'hex').readUInt32LE(4); + //DEBUG console.log("ref_block",@ref_block_num,@ref_block_prefix,r) + + var iterable = _this2.operations; + for (var i = 0, op; i < iterable.length; i++) { + op = iterable[i]; + if (op[1]["finalize"]) { + op[1].finalize(); + } + + var _type = ops.operation.st_operations[op[0]]; + var hexBuffer = _type.toBuffer(op[1]).toString("hex"); + console.log("Operation %s: %O => %s (%d bytes)", _type.operation_name, op[1], hexBuffer, hexBuffer.length / 2); + } + _this2.tr_buffer = ops.transaction.toBuffer(_this2); + })); + }); + } + + /** @return {string} hex transaction ID */ + + }, { + key: "id", + value: function id() { + if (!this.tr_buffer) { + throw new Error("not finalized"); + } + return hash.sha256(this.tr_buffer).toString('hex').substring(0, 40); + } + + /** + Typically one will use {@link this.add_type_operation} instead. + @arg {array} operation - [operation_id, operation] + */ + + }, { + key: "add_operation", + value: function add_operation(operation) { + if (this.tr_buffer) { + throw new Error("already finalized"); + } + assert(operation, "operation"); + if (!Array.isArray(operation)) { + throw new Error("Expecting array [operation_id, operation]"); + } + this.operations.push(operation); + return; + } + }, { + key: "get_type_operation", + value: function get_type_operation(name, operation) { + if (this.tr_buffer) { + throw new Error("already finalized"); + } + assert(name, "name"); + assert(operation, "operation"); + var _type = ops[name]; + assert(_type, "Unknown operation " + name); + var operation_id = ChainTypes.operations[_type.operation_name]; + if (operation_id === undefined) { + throw new Error("unknown operation: " + _type.operation_name); + } + if (!operation.fee) { + operation.fee = { amount: 0, asset_id: 0 }; + } + if (name === 'proposal_create') { + operation.expiration_time || (operation.expiration_time = base_expiration_sec() + ChainConfig.expire_in_secs_proposal); + } + var operation_instance = _type.fromObject(operation); + return [operation_id, operation_instance]; + } + + /** optional: there is a deafult expiration */ + + }, { + key: "set_expire_seconds", + value: function set_expire_seconds(sec) { + if (this.tr_buffer) { + throw new Error("already finalized"); + } + return this.expiration = base_expiration_sec() + sec; + } + + /* Wraps this transaction in a proposal_create transaction */ + + }, { + key: "propose", + value: function propose(proposal_create_options) { + if (this.tr_buffer) { + throw new Error("already finalized"); + } + if (!this.operations.length) { + throw new Error("add operation first"); + } + + assert(proposal_create_options, "proposal_create_options"); + assert(proposal_create_options.fee_paying_account, "proposal_create_options.fee_paying_account"); + + var proposed_ops = this.operations.map(function (op) { + return { op: op }; + }); + + this.operations = []; + this.signatures = []; + this.signer_private_keys = []; + proposal_create_options.proposed_ops = proposed_ops; + this.add_type_operation("proposal_create", proposal_create_options); + return this; + } + }, { + key: "has_proposed_operation", + value: function has_proposed_operation() { + var hasProposed = false; + for (var i = 0; i < this.operations.length; i++) { + if ("proposed_ops" in this.operations[i][1]) { + hasProposed = true; + break; + } + } + + return hasProposed; + } + + /** optional: the fees can be obtained from the witness node */ + + }, { + key: "set_required_fees", + value: function set_required_fees(asset_id) { + var _this3 = this; + + var fee_pool; + if (this.tr_buffer) { + throw new Error("already finalized"); + } + if (!this.operations.length) { + throw new Error("add operations first"); + } + var operations = []; + for (var i = 0, op; i < this.operations.length; i++) { + op = this.operations[i]; + operations.push(ops.operation.toObject(op)); + } + + if (!asset_id) { + var op1_fee = operations[0][1].fee; + if (op1_fee && op1_fee.asset_id !== null) { + asset_id = op1_fee.asset_id; + } else { + asset_id = "1.3.0"; + } + } + + var promises = [Apis.instance().db_api().exec("get_required_fees", [operations, asset_id])]; + + var feeAssetPromise = null; + if (asset_id !== "1.3.0") { + // This handles the fallback to paying fees in BTS if the fee pool is empty. + promises.push(Apis.instance().db_api().exec("get_required_fees", [operations, "1.3.0"])); + promises.push(Apis.instance().db_api().exec("get_objects", [[asset_id]])); + } + + return Promise.all(promises).then(function (results) { + var _results = _slicedToArray(results, 3), + fees = _results[0], + coreFees = _results[1], + asset = _results[2]; + + asset = asset ? asset[0] : null; + + var dynamicPromise = asset_id !== "1.3.0" && asset ? Apis.instance().db_api().exec("get_objects", [[asset.dynamic_asset_data_id]]) : new Promise(function (resolve, reject) { + resolve(); + }); + + return dynamicPromise.then(function (dynamicObject) { + if (asset_id !== "1.3.0") { + fee_pool = dynamicObject ? dynamicObject[0].fee_pool : 0; + var totalFees = 0; + for (var j = 0, fee; j < coreFees.length; j++) { + fee = coreFees[j]; + totalFees += fee.amount; + } + + if (totalFees > parseInt(fee_pool, 10)) { + fees = coreFees; + asset_id = "1.3.0"; + } + } + + // Proposed transactions need to be flattened + var flat_assets = []; + var flatten = function flatten(obj) { + if (Array.isArray(obj)) { + for (var k = 0, item; k < obj.length; k++) { + item = obj[k]; + flatten(item); + } + } else { + flat_assets.push(obj); + } + return; + }; + flatten(fees); + + var asset_index = 0; + + var set_fee = function set_fee(operation) { + if (!operation.fee || operation.fee.amount === 0 || operation.fee.amount.toString && operation.fee.amount.toString() === "0" // Long + ) { + operation.fee = flat_assets[asset_index]; + // console.log("new operation.fee", operation.fee) + } else { + // console.log("old operation.fee", operation.fee) + } + asset_index++; + if (operation.proposed_ops) { + var result = []; + for (var y = 0; y < operation.proposed_ops.length; y++) { + result.push(set_fee(operation.proposed_ops[y].op[1])); + }return result; + } + }; + for (var _i = 0; _i < _this3.operations.length; _i++) { + set_fee(_this3.operations[_i][1]); + } + }); + //DEBUG console.log('... get_required_fees',operations,asset_id,flat_assets) + }); + } + }, { + key: "get_potential_signatures", + value: function get_potential_signatures() { + var tr_object = ops.signed_transaction.toObject(this); + return Promise.all([Apis.instance().db_api().exec("get_potential_signatures", [tr_object]), Apis.instance().db_api().exec("get_potential_address_signatures", [tr_object])]).then(function (results) { + return { pubkeys: results[0], addys: results[1] }; + }); + } + }, { + key: "get_required_signatures", + value: function get_required_signatures(available_keys) { + if (!available_keys.length) { + return Promise.resolve([]); + } + var tr_object = ops.signed_transaction.toObject(this); + //DEBUG console.log('... tr_object',tr_object) + return Apis.instance().db_api().exec("get_required_signatures", [tr_object, available_keys]).then(function (required_public_keys) { + //DEBUG console.log('... get_required_signatures',required_public_keys) + return required_public_keys; + }); + } + }, { + key: "add_signer", + value: function add_signer(private_key) { + var public_key = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : private_key.toPublicKey(); + + + assert(private_key.d, "required PrivateKey object"); + + if (this.signed) { + throw new Error("already signed"); + } + if (!public_key.Q) { + public_key = PublicKey.fromPublicKeyString(public_key); + } + // prevent duplicates + var spHex = private_key.toHex(); + var _iteratorNormalCompletion3 = true; + var _didIteratorError3 = false; + var _iteratorError3 = undefined; + + try { + for (var _iterator3 = this.signer_private_keys[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) { + var sp = _step3.value; + + if (sp[0].toHex() === spHex) return; + } + } catch (err) { + _didIteratorError3 = true; + _iteratorError3 = err; + } finally { + try { + if (!_iteratorNormalCompletion3 && _iterator3.return) { + _iterator3.return(); + } + } finally { + if (_didIteratorError3) { + throw _iteratorError3; + } + } + } + + this.signer_private_keys.push([private_key, public_key]); + } + }, { + key: "sign", + value: function sign() { + var chain_id = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : Apis.instance().chain_id; + + if (!this.tr_buffer) { + throw new Error("not finalized"); + } + if (this.signed) { + throw new Error("already signed"); + } + if (!this.signer_private_keys.length) { + throw new Error("Transaction was not signed. Do you have a private key? [no_signers]"); + } + var end = this.signer_private_keys.length; + for (var i = 0; 0 < end ? i < end : i > end; 0 < end ? i++ : i++) { + var _signer_private_keys$ = _slicedToArray(this.signer_private_keys[i], 2), + private_key = _signer_private_keys$[0], + public_key = _signer_private_keys$[1]; + + var sig = Signature.signBuffer(Buffer.concat([new Buffer(chain_id, 'hex'), this.tr_buffer]), private_key, public_key); + this.signatures.push(sig.toBuffer()); + } + this.signer_private_keys = []; + this.signed = true; + return; + } + }, { + key: "serialize", + value: function serialize() { + return ops.signed_transaction.toObject(this); + } + }, { + key: "toObject", + value: function toObject() { + return ops.signed_transaction.toObject(this); + } + }, { + key: "broadcast", + value: function broadcast(was_broadcast_callback) { + var _this4 = this; + + if (this.tr_buffer) { + return this._broadcast(was_broadcast_callback); + } else { + return this.finalize().then(function () { + return _this4._broadcast(was_broadcast_callback); + }); + } + } + }]); + + return TransactionBuilder; +}(); + +var base_expiration_sec = function base_expiration_sec() { + var head_block_sec = Math.ceil(getHeadBlockDate().getTime() / 1000); + var now_sec = Math.ceil(Date.now() / 1000); + // The head block time should be updated every 3 seconds. If it isn't + // then help the transaction to expire (use head_block_sec) + if (now_sec - head_block_sec > 30) { + return head_block_sec; + } + // If the user's clock is very far behind, use the head block time. + return Math.max(now_sec, head_block_sec); +}; + +function _broadcast(was_broadcast_callback) { + var _this5 = this; + + return new Promise(function (resolve, reject) { + + if (!_this5.signed) { + _this5.sign(); + } + if (!_this5.tr_buffer) { + throw new Error("not finalized"); + } + if (!_this5.signatures.length) { + throw new Error("not signed"); + } + if (!_this5.operations.length) { + throw new Error("no operations"); + } + + var tr_object = ops.signed_transaction.toObject(_this5); + // console.log('... broadcast_transaction_with_callback !!!') + Apis.instance().network_api().exec("broadcast_transaction_with_callback", [function (res) { + return resolve(res); + }, tr_object]).then(function () { + //console.log('... broadcast success, waiting for callback') + if (was_broadcast_callback) was_broadcast_callback(); + return; + }).catch(function (error) { + // console.log may be redundant for network errors, other errors could occur + console.log(error); + var message = error.message; + if (!message) { + message = ""; + } + reject(new Error(message + "\n" + 'graphene-crypto ' + ' digest ' + hash.sha256(_this5.tr_buffer).toString('hex') + ' transaction ' + _this5.tr_buffer.toString('hex') + ' ' + JSON.stringify(tr_object))); + return; + }); + return; + }); +} + +function getHeadBlockDate() { + return timeStringToDate(head_block_time_string); +} + +function timeStringToDate(time_string) { + if (!time_string) return new Date("1970-01-01T00:00:00.000Z"); + if (!/Z$/.test(time_string)) //does not end in Z + // https://github.com/cryptonomex/graphene/issues/368 + time_string = time_string + "Z"; + return new Date(time_string); +} + +module.exports = TransactionBuilder; \ No newline at end of file diff --git a/dist/chain/src/TransactionHelper.js b/dist/chain/src/TransactionHelper.js new file mode 100644 index 0000000..238173f --- /dev/null +++ b/dist/chain/src/TransactionHelper.js @@ -0,0 +1,104 @@ +'use strict'; + +var helper; +module.exports = helper = {}; + +var secureRandom = require('secure-random'); + +//Promise = require '../common/Promise' + +var _require = require('bytebuffer'), + Long = _require.Long; + +var _require2 = require("../../ecc"), + Signature = _require2.Signature; + +var _require3 = require("../../serializer"), + ops = _require3.ops; + +var _require4 = require("peerplaysjs-ws"), + Apis = _require4.Apis; + +helper.unique_nonce_entropy = null; +helper.unique_nonce_uint64 = function () { + var entropy = helper.unique_nonce_entropy = function () { + + if (helper.unique_nonce_entropy === null) { + //console.log('... secureRandom.randomUint8Array(1)[0]',secureRandom.randomUint8Array(1)[0]) + return parseInt(secureRandom.randomUint8Array(1)[0]); + } else { + return ++helper.unique_nonce_entropy % 256; + } + }(); + var long = Long.fromNumber(Date.now()); + //console.log('unique_nonce_uint64 date\t',ByteBuffer.allocate(8).writeUint64(long).toHex(0)) + //console.log('unique_nonce_uint64 entropy\t',ByteBuffer.allocate(8).writeUint64(Long.fromNumber(entropy)).toHex(0)) + long = long.shiftLeft(8).or(Long.fromNumber(entropy)); + //console.log('unique_nonce_uint64 shift8\t',ByteBuffer.allocate(8).writeUint64(long).toHex(0)) + return long.toString(); +}; + +/* Todo, set fees */ +helper.to_json = function (tr) { + var broadcast = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + return function (tr, broadcast) { + var tr_object = ops.signed_transaction.toObject(tr); + if (broadcast) { + var net = Apis.instance().network_api(); + console.log('... tr_object', JSON.stringify(tr_object)); + return net.exec("broadcast_transaction", [tr_object]); + } else { + return tr_object; + } + }(tr, broadcast); +}; + +helper.signed_tr_json = function (tr, private_keys) { + var tr_buffer = ops.transaction.toBuffer(tr); + tr = ops.transaction.toObject(tr); + tr.signatures = function () { + var result = []; + for (var i = 0; 0 < private_keys.length ? i < private_keys.length : i > private_keys.length; 0 < private_keys.length ? i++ : i++) { + var private_key = private_keys[i]; + result.push(Signature.signBuffer(tr_buffer, private_key).toHex()); + } + return result; + }(); + return tr; +}; + +helper.expire_in_min = function (min) { + return Math.round(Date.now() / 1000) + min * 60; +}; + +helper.seconds_from_now = function (timeout_sec) { + return Math.round(Date.now() / 1000) + timeout_sec; +}; + +/** + Print to the console a JSON representation of any object in + @graphene/serializer { types } +*/ +helper.template = function (serializer_operation_type_name) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { use_default: true, annotate: true }; + + var so = type[serializer_operation_type_name]; + if (!so) { + throw new Error('unknown serializer_operation_type ' + serializer_operation_type_name); + } + return so.toObject(undefined, debug); +}; + +helper.new_operation = function (serializer_operation_type_name) { + var so = type[serializer_operation_type_name]; + if (!so) { + throw new Error('unknown serializer_operation_type ' + serializer_operation_type_name); + } + var object = so.toObject(undefined, { use_default: true, annotate: true }); + return so.fromObject(object); +}; + +helper.instance = function (ObjectId) { + return ObjectId.substring("0.0.".length); +}; \ No newline at end of file diff --git a/dist/chain/src/state.js b/dist/chain/src/state.js new file mode 100644 index 0000000..42971a3 --- /dev/null +++ b/dist/chain/src/state.js @@ -0,0 +1,19 @@ +"use strict"; + +function get(state) { + return function (key) { + return state[key] || ""; + }; +} + +function set(state) { + return function (key, value) { + state[key] = value; + return this; + }; +} + +module.exports = { + get: get, + set: set +}; \ No newline at end of file diff --git a/dist/ecc/index.js b/dist/ecc/index.js new file mode 100644 index 0000000..0444359 --- /dev/null +++ b/dist/ecc/index.js @@ -0,0 +1,12 @@ +"use strict"; + +module.exports = { + Address: require("./src/address"), + Aes: require("./src/aes"), + PrivateKey: require("./src/PrivateKey"), + PublicKey: require("./src/PublicKey"), + Signature: require("./src/signature"), + brainKey: require("./src/BrainKey"), + hash: require("./src/hash"), + key: require("./src/KeyUtils") +}; \ No newline at end of file diff --git a/dist/ecc/src/BrainKey.js b/dist/ecc/src/BrainKey.js new file mode 100644 index 0000000..998b065 --- /dev/null +++ b/dist/ecc/src/BrainKey.js @@ -0,0 +1,9 @@ +'use strict'; + +module.exports = function normalize(brainKey) { + if (typeof brainKey !== 'string') { + throw new Error("string required for brainKey"); + } + brainKey = brainKey.trim(); + return brainKey.split(/[\t\n\v\f\r ]+/).join(' '); +}; \ No newline at end of file diff --git a/dist/ecc/src/KeyUtils.js b/dist/ecc/src/KeyUtils.js new file mode 100644 index 0000000..f993222 --- /dev/null +++ b/dist/ecc/src/KeyUtils.js @@ -0,0 +1,202 @@ +'use strict'; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var key; +var PrivateKey = require('./PrivateKey'); +var PublicKey = require('./PublicKey'); +var Address = require('./address'); +var Aes = require('./aes'); + +var hash = require('./hash'); +// var dictionary = require('./dictionary_en'); +var secureRandom = require('secure-random'); + +var _require = require('peerplaysjs-ws'), + ChainConfig = _require.ChainConfig; + +// hash for .25 second + + +var HASH_POWER_MILLS = 250; + +module.exports = key = { + + /** Uses 1 second of hashing power to create a key/password checksum. An + implementation can re-call this method with the same password to re-match + the strength of the CPU (either after moving from a desktop to a mobile, + mobile to desktop, or N years from now when CPUs are presumably stronger). + A salt is used for all the normal reasons... + @return object { + aes_private: Aes, + checksum: "{hash_iteration_count},{salt},{checksum}" + } + */ + aes_checksum: function aes_checksum(password) { + if (!(typeof password === "string")) { + throw new "password string required"(); + } + var salt = secureRandom.randomBuffer(4).toString('hex'); + var iterations = 0; + var secret = salt + password; + // hash for .1 second + var start_t = Date.now(); + while (Date.now() - start_t < HASH_POWER_MILLS) { + secret = hash.sha256(secret); + iterations += 1; + } + + var checksum = hash.sha256(secret); + var checksum_string = [iterations, salt.toString('hex'), checksum.slice(0, 4).toString('hex')].join(','); + + return { aes_private: Aes.fromSeed(secret), + checksum: checksum_string + }; + }, + + + /** Provide a matching password and key_checksum. A "wrong password" + error is thrown if the password does not match. If this method takes + much more or less than 1 second to return, one should consider updating + all encyrpted fields using a new key.key_checksum. + */ + aes_private: function aes_private(password, key_checksum) { + var _key_checksum$split = key_checksum.split(','), + _key_checksum$split2 = _slicedToArray(_key_checksum$split, 3), + iterations = _key_checksum$split2[0], + salt = _key_checksum$split2[1], + checksum = _key_checksum$split2[2]; + + var secret = salt + password; + for (var i = 0; 0 < iterations ? i < iterations : i > iterations; 0 < iterations ? i++ : i++) { + secret = hash.sha256(secret); + } + var new_checksum = hash.sha256(secret); + if (!(new_checksum.slice(0, 4).toString('hex') === checksum)) { + throw new Error("wrong password"); + } + return Aes.fromSeed(secret); + }, + + + /** + A week random number generator can run out of entropy. This should ensure even the worst random number implementation will be reasonably safe. + @param1 string entropy of at least 32 bytes + */ + random32ByteBuffer: function random32ByteBuffer() { + var entropy = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.browserEntropy(); + + + if (!(typeof entropy === 'string')) { + throw new Error("string required for entropy"); + } + + if (entropy.length < 32) { + throw new Error("expecting at least 32 bytes of entropy"); + } + + var start_t = Date.now(); + + while (Date.now() - start_t < HASH_POWER_MILLS) { + entropy = hash.sha256(entropy); + }var hash_array = []; + hash_array.push(entropy); + + // Hashing for 1 second may helps the computer is not low on entropy (this method may be called back-to-back). + hash_array.push(secureRandom.randomBuffer(32)); + + return hash.sha256(Buffer.concat(hash_array)); + }, + + + suggest_brain_key: function suggest_brain_key() { + var dictionary = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ","; + var entropy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : this.browserEntropy(); + + + var randomBuffer = this.random32ByteBuffer(entropy); + + var word_count = 16; + var dictionary_lines = dictionary.split(','); + + if (!(dictionary_lines.length === 49744)) { + throw new Error('expecting ' + 49744 + ' but got ' + dictionary_lines.length + ' dictionary words'); + } + + var brainkey = []; + var end = word_count * 2; + + for (var i = 0; i < end; i += 2) { + + // randomBuffer has 256 bits / 16 bits per word == 16 words + var num = (randomBuffer[i] << 8) + randomBuffer[i + 1]; + + // convert into a number between 0 and 1 (inclusive) + var rndMultiplier = num / Math.pow(2, 16); + var wordIndex = Math.round(dictionary_lines.length * rndMultiplier); + + brainkey.push(dictionary_lines[wordIndex]); + } + return this.normalize_brainKey(brainkey.join(' ')); + }, + + get_random_key: function get_random_key(entropy) { + return PrivateKey.fromBuffer(this.random32ByteBuffer(entropy)); + }, + get_brainPrivateKey: function get_brainPrivateKey(brainKey) { + var sequence = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; + + if (sequence < 0) { + throw new Error("invalid sequence"); + } + brainKey = key.normalize_brainKey(brainKey); + return PrivateKey.fromBuffer(hash.sha256(hash.sha512(brainKey + " " + sequence))); + }, + + + // Turn invisible space like characters into a single space + normalize_brainKey: function normalize_brainKey(brainKey) { + if (!(typeof brainKey === 'string')) { + throw new Error("string required for brainKey"); + } + + brainKey = brainKey.trim(); + return brainKey.split(/[\t\n\v\f\r ]+/).join(' '); + }, + browserEntropy: function browserEntropy() { + + var entropyStr = ""; + try { + entropyStr = new Date().toString() + " " + window.screen.height + " " + window.screen.width + " " + window.screen.colorDepth + " " + " " + window.screen.availHeight + " " + window.screen.availWidth + " " + window.screen.pixelDepth + navigator.language + " " + window.location + " " + window.history.length; + + for (var i = 0, mimeType; i < navigator.mimeTypes.length; i++) { + mimeType = navigator.mimeTypes[i]; + entropyStr += mimeType.description + " " + mimeType.type + " " + mimeType.suffixes + " "; + } + console.log("INFO\tbrowserEntropy gathered"); + } catch (error) { + //nodejs:ReferenceError: window is not defined + entropyStr = hash.sha256(new Date().toString()); + } + + var b = new Buffer(entropyStr); + entropyStr += b.toString('binary') + " " + new Date().toString(); + return entropyStr; + }, + + + // @return array of 5 legacy addresses for a pubkey string parameter. + addresses: function addresses(pubkey) { + var address_prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ChainConfig.address_prefix; + + var public_key = PublicKey.fromPublicKeyString(pubkey, address_prefix); + // S L O W + var address_string = [Address.fromPublic(public_key, false, 0).toString(address_prefix), // btc_uncompressed + Address.fromPublic(public_key, true, 0).toString(address_prefix), // btc_compressed + Address.fromPublic(public_key, false, 56).toString(address_prefix), // pts_uncompressed + Address.fromPublic(public_key, true, 56).toString(address_prefix), // pts_compressed + public_key.toAddressString(address_prefix) // bts_short, most recent format + ]; + return address_string; + } +}; \ No newline at end of file diff --git a/dist/ecc/src/PrivateKey.js b/dist/ecc/src/PrivateKey.js new file mode 100644 index 0000000..8f4bfdc --- /dev/null +++ b/dist/ecc/src/PrivateKey.js @@ -0,0 +1,213 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ecurve = require('ecurve'); + +var _require = require('ecurve'), + Point = _require.Point, + getCurveByName = _require.getCurveByName; + +var secp256k1 = getCurveByName('secp256k1'); +var BigInteger = require('bigi'); + +var _require2 = require('bs58'), + encode = _require2.encode, + decode = _require2.decode; + +var assert = require('assert'); +var hash = require('./hash'); +var PublicKey = require('./PublicKey'); +var deepEqual = require("deep-equal"); + +var G = secp256k1.G, + n = secp256k1.n; + +var PrivateKey = function () { + + /** + @private see static functions + @param {BigInteger} + */ + function PrivateKey(d) { + _classCallCheck(this, PrivateKey); + + this.d = d; + } + + _createClass(PrivateKey, [{ + key: 'toWif', + value: function toWif() { + var private_key = this.toBuffer(); + // checksum includes the version + private_key = Buffer.concat([new Buffer([0x80]), private_key]); + var checksum = hash.sha256(private_key); + checksum = hash.sha256(checksum); + checksum = checksum.slice(0, 4); + var private_wif = Buffer.concat([private_key, checksum]); + return encode(private_wif); + } + + /** + @return {Point} + */ + + }, { + key: 'toPublicKeyPoint', + value: function toPublicKeyPoint() { + var Q; + return Q = secp256k1.G.multiply(this.d); + } + }, { + key: 'toPublicKey', + value: function toPublicKey() { + if (this.public_key) { + return this.public_key; + } + return this.public_key = PublicKey.fromPoint(this.toPublicKeyPoint()); + } + }, { + key: 'toBuffer', + value: function toBuffer() { + return this.d.toBuffer(32); + } + + /** ECIES */ + + }, { + key: 'get_shared_secret', + value: function get_shared_secret(public_key) { + var legacy = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; + + public_key = toPublic(public_key); + var KB = public_key.toUncompressed().toBuffer(); + var KBP = Point.fromAffine(secp256k1, BigInteger.fromBuffer(KB.slice(1, 33)), // x + BigInteger.fromBuffer(KB.slice(33, 65)) // y + ); + var r = this.toBuffer(); + var P = KBP.multiply(BigInteger.fromBuffer(r)); + var S = P.affineX.toBuffer({ size: 32 }); + /* + the input to sha512 must be exactly 32-bytes, to match the c++ implementation + of get_shared_secret. Right now S will be shorter if the most significant + byte(s) is zero. Pad it back to the full 32-bytes + */ + if (!legacy && S.length < 32) { + pad = new Buffer(32 - S.length).fill(0); + S = Buffer.concat([pad, S]); + } + + // SHA512 used in ECIES + return hash.sha512(S); + } + + // /** ECIES (does not always match the Point.fromAffine version above) */ + // get_shared_secret(public_key){ + // public_key = toPublic(public_key) + // var P = public_key.Q.multiply( this.d ); + // var S = P.affineX.toBuffer({size: 32}); + // // ECIES, adds an extra sha512 + // return hash.sha512(S); + // } + + /** @throws {Error} - overflow of the key could not be derived */ + + }, { + key: 'child', + value: function child(offset) { + offset = Buffer.concat([this.toPublicKey().toBuffer(), offset]); + offset = hash.sha256(offset); + var c = BigInteger.fromBuffer(offset); + + if (c.compareTo(n) >= 0) throw new Error("Child offset went out of bounds, try again"); + + var derived = this.d.add(c); //.mod(n) + + if (derived.signum() === 0) throw new Error("Child offset derived to an invalid key, try again"); + + return new PrivateKey(derived); + } + + /* */ + + }, { + key: 'toByteBuffer', + value: function toByteBuffer() { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + this.appendByteBuffer(b); + return b.copy(0, b.offset); + } + }, { + key: 'toHex', + value: function toHex() { + return this.toBuffer().toString('hex'); + } + + /* */ + + }], [{ + key: 'fromBuffer', + value: function fromBuffer(buf) { + if (!Buffer.isBuffer(buf)) { + throw new Error("Expecting paramter to be a Buffer type"); + } + if (32 !== buf.length) { + console.log('WARN: Expecting 32 bytes, instead got ' + buf.length + ', stack trace:', new Error().stack); + } + if (buf.length === 0) { + throw new Error("Empty buffer"); + } + return new PrivateKey(BigInteger.fromBuffer(buf)); + } + + /** @arg {string} seed - any length string. This is private, the same seed produces the same private key every time. */ + + }, { + key: 'fromSeed', + value: function fromSeed(seed) { + // generate_private_key + if (!(typeof seed === 'string')) { + throw new Error('seed must be of type string'); + } + return PrivateKey.fromBuffer(hash.sha256(seed)); + } + + /** @return {string} Wallet Import Format (still a secret, Not encrypted) */ + + }, { + key: 'fromWif', + value: function fromWif(_private_wif) { + var private_wif = new Buffer(decode(_private_wif)); + var version = private_wif.readUInt8(0); + assert.equal(0x80, version, 'Expected version ' + 0x80 + ', instead got ' + version); + // checksum includes the version + var private_key = private_wif.slice(0, -4); + var checksum = private_wif.slice(-4); + var new_checksum = hash.sha256(private_key); + new_checksum = hash.sha256(new_checksum); + new_checksum = new_checksum.slice(0, 4); + var isEqual = deepEqual(checksum, new_checksum); //, 'Invalid checksum' + if (!isEqual) { + throw new Error("Checksum did not match"); + } + private_key = private_key.slice(1); + private_key = private_key.slice(0, 32); + return PrivateKey.fromBuffer(private_key); + } + }, { + key: 'fromHex', + value: function fromHex(hex) { + return PrivateKey.fromBuffer(new Buffer(hex, 'hex')); + } + }]); + + return PrivateKey; +}(); + +module.exports = PrivateKey; + +var toPublic = function toPublic(data) { + return data == null ? data : data.Q ? data : PublicKey.fromStringOrThrow(data); +}; \ No newline at end of file diff --git a/dist/ecc/src/PublicKey.js b/dist/ecc/src/PublicKey.js new file mode 100644 index 0000000..a04d063 --- /dev/null +++ b/dist/ecc/src/PublicKey.js @@ -0,0 +1,236 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var BigInteger = require('bigi'); + +var _require = require('ecurve'), + Point = _require.Point, + getCurveByName = _require.getCurveByName; + +var secp256k1 = getCurveByName('secp256k1'); + +var _require2 = require('bs58'), + encode = _require2.encode, + decode = _require2.decode; + +var hash = require('./hash'); + +var _require3 = require('peerplaysjs-ws'), + ChainConfig = _require3.ChainConfig; + +var assert = require('assert'); +var deepEqual = require("deep-equal"); + +var G = secp256k1.G, + n = secp256k1.n; + +var PublicKey = function () { + + /** @param {Point} public key */ + function PublicKey(Q) { + _classCallCheck(this, PublicKey); + + this.Q = Q; + } + + _createClass(PublicKey, [{ + key: 'toBuffer', + value: function toBuffer() { + var compressed = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.Q ? this.Q.compressed : null; + + if (this.Q === null) return new Buffer('000000000000000000000000000000000000000000000000000000000000000000', 'hex'); + return this.Q.getEncoded(compressed); + } + }, { + key: 'toUncompressed', + value: function toUncompressed() { + var buf = this.Q.getEncoded(false); + var point = Point.decodeFrom(secp256k1, buf); + return PublicKey.fromPoint(point); + } + + /** bts::blockchain::address (unique but not a full public key) */ + + }, { + key: 'toBlockchainAddress', + value: function toBlockchainAddress() { + var pub_buf = this.toBuffer(); + var pub_sha = hash.sha512(pub_buf); + return hash.ripemd160(pub_sha); + } + + /** Alias for {@link toPublicKeyString} */ + + }, { + key: 'toString', + value: function toString() { + var address_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ChainConfig.address_prefix; + + return this.toPublicKeyString(address_prefix); + } + + /** + Full public key + {return} string + */ + + }, { + key: 'toPublicKeyString', + value: function toPublicKeyString() { + var address_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ChainConfig.address_prefix; + + var pub_buf = this.toBuffer(); + var checksum = hash.ripemd160(pub_buf); + // Slice from the buffer directly, slicing from the checksum Uint8array will return the entire array each time. + var sliced = new Uint8Array(checksum.buffer.slice(0, 4)); + + // concat only accepts buffers so initialize the sliced Uint8array as a Buffer. + var addy = Buffer.concat([pub_buf, Buffer.from(sliced)]); + return address_prefix + encode(addy); + } + + /** + @arg {string} public_key - like GPHXyz... + @arg {string} address_prefix - like GPH + @return PublicKey or `null` (if the public_key string is invalid) + */ + + }, { + key: 'toAddressString', + value: function toAddressString() { + var address_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ChainConfig.address_prefix; + + var pub_buf = this.toBuffer(); + var pub_sha = hash.sha512(pub_buf); + var addy = hash.ripemd160(pub_sha); + var checksum = hash.ripemd160(addy); + addy = Buffer.concat([addy, checksum.slice(0, 4)]); + return address_prefix + encode(addy); + } + }, { + key: 'toPtsAddy', + value: function toPtsAddy() { + var pub_buf = this.toBuffer(); + var pub_sha = hash.sha256(pub_buf); + var addy = hash.ripemd160(pub_sha); + addy = Buffer.concat([new Buffer([0x38]), addy]); //version 56(decimal) + + var checksum = hash.sha256(addy); + checksum = hash.sha256(checksum); + + addy = Buffer.concat([addy, checksum.slice(0, 4)]); + return encode(addy); + } + }, { + key: 'child', + value: function child(offset) { + + assert(Buffer.isBuffer(offset), "Buffer required: offset"); + assert.equal(offset.length, 32, "offset length"); + + offset = Buffer.concat([this.toBuffer(), offset]); + offset = hash.sha256(offset); + + var c = BigInteger.fromBuffer(offset); + + if (c.compareTo(n) >= 0) throw new Error("Child offset went out of bounds, try again"); + + var cG = G.multiply(c); + var Qprime = this.Q.add(cG); + + if (secp256k1.isInfinity(Qprime)) throw new Error("Child offset derived to an invalid key, try again"); + + return PublicKey.fromPoint(Qprime); + } + + /* */ + + }, { + key: 'toByteBuffer', + value: function toByteBuffer() { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + this.appendByteBuffer(b); + return b.copy(0, b.offset); + } + }, { + key: 'toHex', + value: function toHex() { + return this.toBuffer().toString('hex'); + } + }], [{ + key: 'fromBinary', + value: function fromBinary(bin) { + return PublicKey.fromBuffer(new Buffer(bin, 'binary')); + } + }, { + key: 'fromBuffer', + value: function fromBuffer(buffer) { + if (buffer.toString('hex') === '000000000000000000000000000000000000000000000000000000000000000000') return new PublicKey(null); + return new PublicKey(Point.decodeFrom(secp256k1, buffer)); + } + }, { + key: 'fromPoint', + value: function fromPoint(point) { + return new PublicKey(point); + } + }, { + key: 'fromPublicKeyString', + value: function fromPublicKeyString(public_key) { + var address_prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ChainConfig.address_prefix; + + try { + return PublicKey.fromStringOrThrow(public_key, address_prefix); + } catch (e) { + return null; + } + } + + /** + @arg {string} public_key - like GPHXyz... + @arg {string} address_prefix - like GPH + @throws {Error} if public key is invalid + @return PublicKey + */ + + }, { + key: 'fromStringOrThrow', + value: function fromStringOrThrow(public_key) { + var address_prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ChainConfig.address_prefix; + + var prefix = public_key.slice(0, address_prefix.length); + assert.equal(address_prefix, prefix, 'Expecting key to begin with ' + address_prefix + ', instead got ' + prefix); + public_key = public_key.slice(address_prefix.length); + + public_key = new Buffer(decode(public_key), 'binary'); + var checksum = public_key.slice(-4); + public_key = public_key.slice(0, -4); + var new_checksum = hash.ripemd160(public_key); + new_checksum = new_checksum.slice(0, 4); + var isEqual = deepEqual(checksum, new_checksum); //, 'Invalid checksum' + if (!isEqual) { + throw new Error("Checksum did not match"); + } + return PublicKey.fromBuffer(public_key); + } + }, { + key: 'fromHex', + value: function fromHex(hex) { + return PublicKey.fromBuffer(new Buffer(hex, 'hex')); + } + }, { + key: 'fromPublicKeyStringHex', + value: function fromPublicKeyStringHex(hex) { + return PublicKey.fromPublicKeyString(new Buffer(hex, 'hex')); + } + + /* */ + + }]); + + return PublicKey; +}(); + +module.exports = PublicKey; \ No newline at end of file diff --git a/dist/ecc/src/address.js b/dist/ecc/src/address.js new file mode 100644 index 0000000..919b85d --- /dev/null +++ b/dist/ecc/src/address.js @@ -0,0 +1,95 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var assert = require('assert'); + +var _require = require('peerplaysjs-ws'), + ChainConfig = _require.ChainConfig; + +var hash = require('./hash'); + +var _require2 = require('bs58'), + encode = _require2.encode, + decode = _require2.decode; + +var deepEqual = require("deep-equal"); + +/** Addresses are shortened non-reversable hashes of a public key. The full PublicKey is preferred. + @deprecated +*/ + +var Address = function () { + function Address(addy) { + _classCallCheck(this, Address); + + this.addy = addy; + } + + _createClass(Address, [{ + key: 'toBuffer', + value: function toBuffer() { + return this.addy; + } + }, { + key: 'toString', + value: function toString() { + var address_prefix = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ChainConfig.address_prefix; + + var checksum = hash.ripemd160(this.addy); + var addy = Buffer.concat([this.addy, checksum.slice(0, 4)]); + return address_prefix + encode(addy); + } + }], [{ + key: 'fromBuffer', + value: function fromBuffer(buffer) { + var _hash = hash.sha512(buffer); + var addy = hash.ripemd160(_hash); + return new Address(addy); + } + }, { + key: 'fromString', + value: function fromString(string) { + var address_prefix = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ChainConfig.address_prefix; + + var prefix = string.slice(0, address_prefix.length); + assert.equal(address_prefix, prefix, 'Expecting key to begin with ' + address_prefix + ', instead got ' + prefix); + var addy = string.slice(address_prefix.length); + addy = new Buffer(decode(addy), 'binary'); + var checksum = addy.slice(-4); + addy = addy.slice(0, -4); + var new_checksum = hash.ripemd160(addy); + new_checksum = new_checksum.slice(0, 4); + var isEqual = deepEqual(checksum, new_checksum); //, 'Invalid checksum' + if (!isEqual) { + throw new Error("Checksum did not match"); + } + return new Address(addy); + } + }, { + key: 'fromPublic', + + + /** @return Address - Compressed PTS format (by default) */ + value: function fromPublic(public_key) { + var compressed = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; + var version = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 56; + + var sha2 = hash.sha256(public_key.toBuffer(compressed)); + var rep = hash.ripemd160(sha2); + var versionBuffer = new Buffer(1); + versionBuffer.writeUInt8(0xFF & version, 0); + var addr = Buffer.concat([versionBuffer, rep]); + var check = hash.sha256(addr); + check = hash.sha256(check); + var buffer = Buffer.concat([addr, check.slice(0, 4)]); + return new Address(hash.ripemd160(buffer)); + } + }]); + + return Address; +}(); + +module.exports = Address; \ No newline at end of file diff --git a/dist/ecc/src/aes.js b/dist/ecc/src/aes.js new file mode 100644 index 0000000..42f7487 --- /dev/null +++ b/dist/ecc/src/aes.js @@ -0,0 +1,308 @@ +"use strict"; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +// https://code.google.com/p/crypto-js +var AES = require("crypto-js/aes"); +var encHex = require("crypto-js/enc-hex"); +var encBase64 = require("crypto-js/enc-base64"); +var assert = require("assert"); + +var _require = require("bytebuffer"), + Long = _require.Long; + +var hash = require('./hash'); + +/** Provides symetric encrypt and decrypt via AES. */ + +var Aes = function () { + + /** @private */ + function Aes(iv, key) { + _classCallCheck(this, Aes); + + this.iv = iv, this.key = key; + } + + /** This is an excellent way to ensure that all references to Aes can not operate anymore (example: a wallet becomes locked). An application should ensure there is only one Aes object instance for a given secret `seed`. */ + + + _createClass(Aes, [{ + key: "clear", + value: function clear() { + return this.iv = this.key = undefined; + } + + /** @arg {string} seed - secret seed may be used to encrypt or decrypt. */ + + }, { + key: "_decrypt_word_array", + + + /** @private */ + value: function _decrypt_word_array(cipher) { + // https://code.google.com/p/crypto-js/#Custom_Key_and_IV + // see wallet_records.cpp master_key::decrypt_key + return AES.decrypt({ ciphertext: cipher, salt: null }, this.key, { iv: this.iv }); + } + + /** @private */ + + }, { + key: "_encrypt_word_array", + value: function _encrypt_word_array(plaintext) { + //https://code.google.com/p/crypto-js/issues/detail?id=85 + var cipher = AES.encrypt(plaintext, this.key, { iv: this.iv }); + return encBase64.parse(cipher.toString()); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} ciphertext + @return {Buffer} binary + */ + + }, { + key: "decrypt", + value: function decrypt(ciphertext) { + if (typeof ciphertext === "string") { + ciphertext = new Buffer(ciphertext, 'binary'); + } + if (!Buffer.isBuffer(ciphertext)) { + throw new Error("buffer required"); + } + assert(ciphertext, "Missing cipher text"); + // hex is the only common format + var hex = this.decryptHex(ciphertext.toString('hex')); + return new Buffer(hex, 'hex'); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} plaintext + @return {Buffer} binary + */ + + }, { + key: "encrypt", + value: function encrypt(plaintext) { + if (typeof plaintext === "string") { + plaintext = new Buffer(plaintext, 'binary'); + } + if (!Buffer.isBuffer(plaintext)) { + throw new Error("buffer required"); + } + //assert plaintext, "Missing plain text" + // hex is the only common format + var hex = this.encryptHex(plaintext.toString('hex')); + return new Buffer(hex, 'hex'); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string|Buffer} plaintext + @return {string} hex + */ + + }, { + key: "encryptToHex", + value: function encryptToHex(plaintext) { + if (typeof plaintext === "string") { + plaintext = new Buffer(plaintext, 'binary'); + } + if (!Buffer.isBuffer(plaintext)) { + throw new Error("buffer required"); + } + //assert plaintext, "Missing plain text" + // hex is the only common format + return this.encryptHex(plaintext.toString('hex')); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} cipher - hex + @return {string} binary (could easily be readable text) + */ + + }, { + key: "decryptHex", + value: function decryptHex(cipher) { + assert(cipher, "Missing cipher text"); + // Convert data into word arrays (used by Crypto) + var cipher_array = encHex.parse(cipher); + var plainwords = this._decrypt_word_array(cipher_array); + return encHex.stringify(plainwords); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} cipher - hex + @return {Buffer} encoded as specified by the parameter + */ + + }, { + key: "decryptHexToBuffer", + value: function decryptHexToBuffer(cipher) { + assert(cipher, "Missing cipher text"); + // Convert data into word arrays (used by Crypto) + var cipher_array = encHex.parse(cipher); + var plainwords = this._decrypt_word_array(cipher_array); + var plainhex = encHex.stringify(plainwords); + return new Buffer(plainhex, 'hex'); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} cipher - hex + @arg {string} [encoding = 'binary'] - a valid Buffer encoding + @return {String} encoded as specified by the parameter + */ + + }, { + key: "decryptHexToText", + value: function decryptHexToText(cipher) { + var encoding = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'binary'; + + return this.decryptHexToBuffer(cipher).toString(encoding); + } + + /** This method does not use a checksum, the returned data must be validated some other way. + @arg {string} plainhex - hex format + @return {String} hex + */ + + }, { + key: "encryptHex", + value: function encryptHex(plainhex) { + var plain_array = encHex.parse(plainhex); + var cipher_array = this._encrypt_word_array(plain_array); + return encHex.stringify(cipher_array); + } + }], [{ + key: "fromSeed", + value: function fromSeed(seed) { + if (seed === undefined) { + throw new Error("seed is required"); + } + var _hash = hash.sha512(seed); + _hash = _hash.toString('hex'); + // DEBUG console.log('... fromSeed _hash',_hash) + return Aes.fromSha512(_hash); + } + }, { + key: "fromSha512", + + + /** @arg {string} hash - A 128 byte hex string, typically one would call {@link fromSeed} instead. */ + value: function fromSha512(hash) { + assert.equal(hash.length, 128, "A Sha512 in HEX should be 128 characters long, instead got " + hash.length); + var iv = encHex.parse(hash.substring(64, 96)); + var key = encHex.parse(hash.substring(0, 64)); + return new Aes(iv, key); + } + }, { + key: "fromBuffer", + value: function fromBuffer(buf) { + assert(Buffer.isBuffer(buf), "Expecting Buffer"); + assert.equal(buf.length, 64, "A Sha512 Buffer should be 64 characters long, instead got " + buf.length); + return Aes.fromSha512(buf.toString("hex")); + } + /** + @throws {Error} - "Invalid Key, ..." + @arg {PrivateKey} private_key - required and used for decryption + @arg {PublicKey} public_key - required and used to calcualte the shared secret + @arg {string} [nonce = ""] optional but should always be provided and be unique when re-using the same private/public keys more than once. This nonce is not a secret. + @arg {string|Buffer} message - Encrypted message containing a checksum + @return {Buffer} + */ + + }, { + key: "decrypt_with_checksum", + value: function decrypt_with_checksum(private_key, public_key, nonce, message) { + var legacy = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; + + + // Warning: Do not put `nonce = ""` in the arguments, in es6 this will not convert "null" into an emtpy string + if (nonce == null) // null or undefined + nonce = ""; + + if (!Buffer.isBuffer(message)) { + message = new Buffer(message, 'hex'); + } + + var S = private_key.get_shared_secret(public_key, legacy); + // D E B U G + // console.log('decrypt_with_checksum', { + // priv_to_pub: private_key.toPublicKey().toString(), + // pub: public_key.toPublicKeyString(), + // nonce: nonce, + // message: message.length, + // S: S.toString('hex') + // }) + + var aes = Aes.fromSeed(Buffer.concat([ + // A null or empty string nonce will not effect the hash + new Buffer("" + nonce), new Buffer(S.toString('hex'))])); + + var planebuffer = aes.decrypt(message); + if (!(planebuffer.length >= 4)) { + throw new Error("Invalid key, could not decrypt message(1)"); + } + + // DEBUG console.log('... planebuffer',planebuffer) + var checksum = planebuffer.slice(0, 4); + var plaintext = planebuffer.slice(4); + + // console.log('... checksum',checksum.toString('hex')) + // console.log('... plaintext',plaintext.toString()) + + var new_checksum = hash.sha256(plaintext); + new_checksum = new_checksum.slice(0, 4); + new_checksum = new_checksum.toString('hex'); + + if (!(checksum.toString('hex') === new_checksum)) { + throw new Error("Invalid key, could not decrypt message(2)"); + } + + return plaintext; + } + }, { + key: "encrypt_with_checksum", + + + /** Identical to {@link decrypt_with_checksum} but used to encrypt. Should not throw an error. + @return {Buffer} message - Encrypted message which includes a checksum + */ + value: function encrypt_with_checksum(private_key, public_key, nonce, message) { + + // Warning: Do not put `nonce = ""` in the arguments, in es6 this will not convert "null" into an emtpy string + + if (nonce == null) // null or undefined + nonce = ""; + + if (!Buffer.isBuffer(message)) { + message = new Buffer(message, 'binary'); + } + + var S = private_key.get_shared_secret(public_key); + + // D E B U G + // console.log('encrypt_with_checksum', { + // priv_to_pub: private_key.toPublicKey().toString() + // pub: public_key.toPublicKeyString() + // nonce: nonce + // message: message.length + // S: S.toString('hex') + // }) + + var aes = Aes.fromSeed(Buffer.concat([ + // A null or empty string nonce will not effect the hash + new Buffer("" + nonce), new Buffer(S.toString('hex'))])); + // DEBUG console.log('... S',S.toString('hex')) + var checksum = hash.sha256(message).slice(0, 4); + var payload = Buffer.concat([checksum, message]); + // DEBUG console.log('... payload',payload.toString()) + return aes.encrypt(payload); + } + }]); + + return Aes; +}(); + +module.exports = Aes; \ No newline at end of file diff --git a/dist/ecc/src/ecdsa.js b/dist/ecc/src/ecdsa.js new file mode 100644 index 0000000..959a5da --- /dev/null +++ b/dist/ecc/src/ecdsa.js @@ -0,0 +1,219 @@ +'use strict'; + +var assert = require('assert'); // from github.com/bitcoinjs/bitcoinjs-lib from github.com/cryptocoinjs/ecdsa +var crypto = require('./hash'); +var enforceType = require('./enforce_types'); + +var BigInteger = require('bigi'); +var ECSignature = require('./ecsignature'); + +// https://tools.ietf.org/html/rfc6979#section-3.2 +function deterministicGenerateK(curve, hash, d, checkSig, nonce) { + + enforceType('Buffer', hash); + enforceType(BigInteger, d); + + if (nonce) { + hash = crypto.sha256(Buffer.concat([hash, new Buffer(nonce)])); + } + + // sanity check + assert.equal(hash.length, 32, 'Hash must be 256 bit'); + + var x = d.toBuffer(32); + var k = new Buffer(32); + var v = new Buffer(32); + + // Step B + v.fill(1); + + // Step C + k.fill(0); + + // Step D + k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0]), x, hash]), k); + + // Step E + v = crypto.HmacSHA256(v, k); + + // Step F + k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([1]), x, hash]), k); + + // Step G + v = crypto.HmacSHA256(v, k); + + // Step H1/H2a, ignored as tlen === qlen (256 bit) + // Step H2b + v = crypto.HmacSHA256(v, k); + + var T = BigInteger.fromBuffer(v); + + // Step H3, repeat until T is within the interval [1, n - 1] + while (T.signum() <= 0 || T.compareTo(curve.n) >= 0 || !checkSig(T)) { + k = crypto.HmacSHA256(Buffer.concat([v, new Buffer([0])]), k); + v = crypto.HmacSHA256(v, k); + + // Step H1/H2a, again, ignored as tlen === qlen (256 bit) + // Step H2b again + v = crypto.HmacSHA256(v, k); + + T = BigInteger.fromBuffer(v); + } + + return T; +} + +function sign(curve, hash, d, nonce) { + + var e = BigInteger.fromBuffer(hash); + var n = curve.n; + var G = curve.G; + + var r, s; + var k = deterministicGenerateK(curve, hash, d, function (k) { + // find canonically valid signature + var Q = G.multiply(k); + + if (curve.isInfinity(Q)) return false; + + r = Q.affineX.mod(n); + if (r.signum() === 0) return false; + + s = k.modInverse(n).multiply(e.add(d.multiply(r))).mod(n); + if (s.signum() === 0) return false; + + return true; + }, nonce); + + var N_OVER_TWO = n.shiftRight(1); + + // enforce low S values, see bip62: 'low s values in signatures' + if (s.compareTo(N_OVER_TWO) > 0) { + s = n.subtract(s); + } + + return new ECSignature(r, s); +} + +function verifyRaw(curve, e, signature, Q) { + var n = curve.n; + var G = curve.G; + + var r = signature.r; + var s = signature.s; + + // 1.4.1 Enforce r and s are both integers in the interval [1, n − 1] + if (r.signum() <= 0 || r.compareTo(n) >= 0) return false; + if (s.signum() <= 0 || s.compareTo(n) >= 0) return false; + + // c = s^-1 mod n + var c = s.modInverse(n); + + // 1.4.4 Compute u1 = es^−1 mod n + // u2 = rs^−1 mod n + var u1 = e.multiply(c).mod(n); + var u2 = r.multiply(c).mod(n); + + // 1.4.5 Compute R = (xR, yR) = u1G + u2Q + var R = G.multiplyTwo(u1, Q, u2); + + // 1.4.5 (cont.) Enforce R is not at infinity + if (curve.isInfinity(R)) return false; + + // 1.4.6 Convert the field element R.x to an integer + var xR = R.affineX; + + // 1.4.7 Set v = xR mod n + var v = xR.mod(n); + + // 1.4.8 If v = r, output "valid", and if v != r, output "invalid" + return v.equals(r); +} + +function verify(curve, hash, signature, Q) { + // 1.4.2 H = Hash(M), already done by the user + // 1.4.3 e = H + var e = BigInteger.fromBuffer(hash); + return verifyRaw(curve, e, signature, Q); +} + +/** + * Recover a public key from a signature. + * + * See SEC 1: Elliptic Curve Cryptography, section 4.1.6, "Public + * Key Recovery Operation". + * + * http://www.secg.org/download/aid-780/sec1-v2.pdf + */ +function recoverPubKey(curve, e, signature, i) { + assert.strictEqual(i & 3, i, 'Recovery param is more than two bits'); + + var n = curve.n; + var G = curve.G; + + var r = signature.r; + var s = signature.s; + + assert(r.signum() > 0 && r.compareTo(n) < 0, 'Invalid r value'); + assert(s.signum() > 0 && s.compareTo(n) < 0, 'Invalid s value'); + + // A set LSB signifies that the y-coordinate is odd + var isYOdd = i & 1; + + // The more significant bit specifies whether we should use the + // first or second candidate key. + var isSecondKey = i >> 1; + + // 1.1 Let x = r + jn + var x = isSecondKey ? r.add(n) : r; + var R = curve.pointFromX(isYOdd, x); + + // 1.4 Check that nR is at infinity + var nR = R.multiply(n); + assert(curve.isInfinity(nR), 'nR is not a valid curve point'); + + // Compute -e from e + var eNeg = e.negate().mod(n); + + // 1.6.1 Compute Q = r^-1 (sR - eG) + // Q = r^-1 (sR + -eG) + var rInv = r.modInverse(n); + + var Q = R.multiplyTwo(s, G, eNeg).multiply(rInv); + curve.validate(Q); + + return Q; +} + +/** + * Calculate pubkey extraction parameter. + * + * When extracting a pubkey from a signature, we have to + * distinguish four different cases. Rather than putting this + * burden on the verifier, Bitcoin includes a 2-bit value with the + * signature. + * + * This function simply tries all four cases and returns the value + * that resulted in a successful pubkey recovery. + */ +function calcPubKeyRecoveryParam(curve, e, signature, Q) { + for (var i = 0; i < 4; i++) { + var Qprime = recoverPubKey(curve, e, signature, i); + + // 1.6.2 Verify Q + if (Qprime.equals(Q)) { + return i; + } + } + + throw new Error('Unable to find valid recovery factor'); +} + +module.exports = { + calcPubKeyRecoveryParam: calcPubKeyRecoveryParam, + deterministicGenerateK: deterministicGenerateK, + recoverPubKey: recoverPubKey, + sign: sign, + verify: verify, + verifyRaw: verifyRaw +}; \ No newline at end of file diff --git a/dist/ecc/src/ecsignature.js b/dist/ecc/src/ecsignature.js new file mode 100644 index 0000000..7debd70 --- /dev/null +++ b/dist/ecc/src/ecsignature.js @@ -0,0 +1,128 @@ +'use strict'; + +var assert = require('assert'); // from https://github.com/bitcoinjs/bitcoinjs-lib +var enforceType = require('./enforce_types'); + +var BigInteger = require('bigi'); + +function ECSignature(r, s) { + enforceType(BigInteger, r); + enforceType(BigInteger, s); + + this.r = r; + this.s = s; +} + +// Import operations +ECSignature.parseCompact = function (buffer) { + assert.equal(buffer.length, 65, 'Invalid signature length'); + var i = buffer.readUInt8(0) - 27; + + // At most 3 bits + assert.equal(i, i & 7, 'Invalid signature parameter'); + var compressed = !!(i & 4); + + // Recovery param only + i = i & 3; + + var r = BigInteger.fromBuffer(buffer.slice(1, 33)); + var s = BigInteger.fromBuffer(buffer.slice(33)); + + return { + compressed: compressed, + i: i, + signature: new ECSignature(r, s) + }; +}; + +ECSignature.fromDER = function (buffer) { + assert.equal(buffer.readUInt8(0), 0x30, 'Not a DER sequence'); + assert.equal(buffer.readUInt8(1), buffer.length - 2, 'Invalid sequence length'); + assert.equal(buffer.readUInt8(2), 0x02, 'Expected a DER integer'); + + var rLen = buffer.readUInt8(3); + assert(rLen > 0, 'R length is zero'); + + var offset = 4 + rLen; + assert.equal(buffer.readUInt8(offset), 0x02, 'Expected a DER integer (2)'); + + var sLen = buffer.readUInt8(offset + 1); + assert(sLen > 0, 'S length is zero'); + + var rB = buffer.slice(4, offset); + var sB = buffer.slice(offset + 2); + offset += 2 + sLen; + + if (rLen > 1 && rB.readUInt8(0) === 0x00) { + assert(rB.readUInt8(1) & 0x80, 'R value excessively padded'); + } + + if (sLen > 1 && sB.readUInt8(0) === 0x00) { + assert(sB.readUInt8(1) & 0x80, 'S value excessively padded'); + } + + assert.equal(offset, buffer.length, 'Invalid DER encoding'); + var r = BigInteger.fromDERInteger(rB); + var s = BigInteger.fromDERInteger(sB); + + assert(r.signum() >= 0, 'R value is negative'); + assert(s.signum() >= 0, 'S value is negative'); + + return new ECSignature(r, s); +}; + +// FIXME: 0x00, 0x04, 0x80 are SIGHASH_* boundary constants, importing Transaction causes a circular dependency +ECSignature.parseScriptSignature = function (buffer) { + var hashType = buffer.readUInt8(buffer.length - 1); + var hashTypeMod = hashType & ~0x80; + + assert(hashTypeMod > 0x00 && hashTypeMod < 0x04, 'Invalid hashType'); + + return { + signature: ECSignature.fromDER(buffer.slice(0, -1)), + hashType: hashType + }; +}; + +// Export operations +ECSignature.prototype.toCompact = function (i, compressed) { + if (compressed) i += 4; + i += 27; + + var buffer = new Buffer(65); + buffer.writeUInt8(i, 0); + + this.r.toBuffer(32).copy(buffer, 1); + this.s.toBuffer(32).copy(buffer, 33); + + return buffer; +}; + +ECSignature.prototype.toDER = function () { + var rBa = this.r.toDERInteger(); + var sBa = this.s.toDERInteger(); + + var sequence = []; + + // INTEGER + sequence.push(0x02, rBa.length); + sequence = sequence.concat(rBa); + + // INTEGER + sequence.push(0x02, sBa.length); + sequence = sequence.concat(sBa); + + // SEQUENCE + sequence.unshift(0x30, sequence.length); + + return new Buffer(sequence); +}; + +ECSignature.prototype.toScriptSignature = function (hashType) { + var hashTypeBuffer = new Buffer(1); + hashTypeBuffer.writeUInt8(hashType, 0); + + return Buffer.concat([this.toDER(), hashTypeBuffer]); +}; + +module.exports = ECSignature; \ No newline at end of file diff --git a/dist/ecc/src/enforce_types.js b/dist/ecc/src/enforce_types.js new file mode 100644 index 0000000..f8bf7b7 --- /dev/null +++ b/dist/ecc/src/enforce_types.js @@ -0,0 +1,49 @@ +'use strict'; + +module.exports = function enforce(type, value) { + // Copied from https://github.com/bitcoinjs/bitcoinjs-lib + switch (type) { + case 'Array': + { + if (Array.isArray(value)) return; + break; + } + + case 'Boolean': + { + if (typeof value === 'boolean') return; + break; + } + + case 'Buffer': + { + if (Buffer.isBuffer(value)) return; + break; + } + + case 'Number': + { + if (typeof value === 'number') return; + break; + } + + case 'String': + { + if (typeof value === 'string') return; + break; + } + + default: + { + if (getName(value.constructor) === getName(type)) return; + } + } + + throw new TypeError('Expected ' + (getName(type) || type) + ', got ' + value); +}; + +function getName(fn) { + // Why not fn.name: https://kangax.github.io/compat-table/es6/#function_name_property + var match = fn.toString().match(/function (.*?)\(/); + return match ? match[1] : null; +} \ No newline at end of file diff --git a/dist/ecc/src/hash.js b/dist/ecc/src/hash.js new file mode 100644 index 0000000..5088cec --- /dev/null +++ b/dist/ecc/src/hash.js @@ -0,0 +1,60 @@ +"use strict"; + +var createHash = require("create-hash"); +var createHmac = require("create-hmac"); + +/** @arg {string|Buffer} data + @arg {string} [digest = null] - 'hex', 'binary' or 'base64' + @return {string|Buffer} - Buffer when digest is null, or string +*/ +function sha1(data, encoding) { + return createHash('sha1').update(data).digest(encoding); +} + +/** @arg {string|Buffer} data + @arg {string} [digest = null] - 'hex', 'binary' or 'base64' + @return {string|Buffer} - Buffer when digest is null, or string +*/ +function sha256(data, encoding) { + return createHash('sha256').update(data).digest(encoding); +} + +/** @arg {string|Buffer} data + @arg {string} [digest = null] - 'hex', 'binary' or 'base64' + @return {string|Buffer} - Buffer when digest is null, or string +*/ +function sha512(data, encoding) { + return createHash('sha512').update(data).digest(encoding); +} + +function HmacSHA256(buffer, secret) { + return createHmac('sha256', secret).update(buffer).digest(); +} + +function ripemd160(data) { + return createHash('rmd160').update(data).digest(); +} + +// function hash160(buffer) { +// return ripemd160(sha256(buffer)) +// } +// +// function hash256(buffer) { +// return sha256(sha256(buffer)) +// } + +// +// function HmacSHA512(buffer, secret) { +// return crypto.createHmac('sha512', secret).update(buffer).digest() +// } + +module.exports = { + sha1: sha1, + sha256: sha256, + sha512: sha512, + HmacSHA256: HmacSHA256, + ripemd160: ripemd160 + // hash160: hash160, + // hash256: hash256, + // HmacSHA512: HmacSHA512 +}; \ No newline at end of file diff --git a/dist/ecc/src/signature.js b/dist/ecc/src/signature.js new file mode 100644 index 0000000..2d27835 --- /dev/null +++ b/dist/ecc/src/signature.js @@ -0,0 +1,187 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ecdsa = require('./ecdsa'); +var hash = require('./hash'); + +var _require = require('ecurve'), + getCurveByName = _require.getCurveByName; + +var secp256k1 = getCurveByName('secp256k1'); +var assert = require('assert'); +var BigInteger = require('bigi'); +var PublicKey = require('./PublicKey'); + +var Signature = function () { + function Signature(r1, s1, i1) { + _classCallCheck(this, Signature); + + this.r = r1; + this.s = s1; + this.i = i1; + assert.equal(this.r != null, true, 'Missing parameter'); + assert.equal(this.s != null, true, 'Missing parameter'); + assert.equal(this.i != null, true, 'Missing parameter'); + } + + _createClass(Signature, [{ + key: 'toBuffer', + value: function toBuffer() { + var buf; + buf = new Buffer(65); + buf.writeUInt8(this.i, 0); + this.r.toBuffer(32).copy(buf, 1); + this.s.toBuffer(32).copy(buf, 33); + return buf; + } + }, { + key: 'recoverPublicKeyFromBuffer', + value: function recoverPublicKeyFromBuffer(buffer) { + return this.recoverPublicKey(hash.sha256(buffer)); + } + }, { + key: 'recoverPublicKey', + + + /** + @return {PublicKey} + */ + value: function recoverPublicKey(sha256_buffer) { + var Q = void 0, + e = void 0, + i = void 0; + e = BigInteger.fromBuffer(sha256_buffer); + i = this.i; + i -= 27; + i = i & 3; + Q = ecdsa.recoverPubKey(secp256k1, e, this, i); + return PublicKey.fromPoint(Q); + } + }, { + key: 'verifyBuffer', + + + /** + @param {Buffer} un-hashed + @param {./PublicKey} + @return {boolean} + */ + value: function verifyBuffer(buf, public_key) { + var _hash = hash.sha256(buf); + return this.verifyHash(_hash, public_key); + } + }, { + key: 'verifyHash', + value: function verifyHash(hash, public_key) { + assert.equal(hash.length, 32, "A SHA 256 should be 32 bytes long, instead got " + hash.length); + return ecdsa.verify(secp256k1, hash, { + r: this.r, + s: this.s + }, public_key.Q); + } + }, { + key: 'toByteBuffer', + + + /* */ + + value: function toByteBuffer() { + var b; + b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + this.appendByteBuffer(b); + return b.copy(0, b.offset); + } + }, { + key: 'toHex', + value: function toHex() { + return this.toBuffer().toString("hex"); + } + }, { + key: 'verifyHex', + value: function verifyHex(hex, public_key) { + var buf; + buf = new Buffer(hex, 'hex'); + return this.verifyBuffer(buf, public_key); + } + }], [{ + key: 'fromBuffer', + value: function fromBuffer(buf) { + var i, r, s; + assert.equal(buf.length, 65, 'Invalid signature length'); + i = buf.readUInt8(0); + assert.equal(i - 27, i - 27 & 7, 'Invalid signature parameter'); + r = BigInteger.fromBuffer(buf.slice(1, 33)); + s = BigInteger.fromBuffer(buf.slice(33)); + return new Signature(r, s, i); + } + }, { + key: 'signBuffer', + + + /** + @param {Buffer} buf + @param {PrivateKey} private_key + @return {Signature} + */ + value: function signBuffer(buf, private_key) { + var _hash = hash.sha256(buf); + return Signature.signBufferSha256(_hash, private_key); + } + + /** Sign a buffer of exactally 32 bytes in size (sha256(text)) + @param {Buffer} buf - 32 bytes binary + @param {PrivateKey} private_key + @return {Signature} + */ + + }, { + key: 'signBufferSha256', + value: function signBufferSha256(buf_sha256, private_key) { + if (buf_sha256.length !== 32 || !Buffer.isBuffer(buf_sha256)) throw new Error("buf_sha256: 32 byte buffer requred"); + var der, e, ecsignature, i, lenR, lenS, nonce; + i = null; + nonce = 0; + e = BigInteger.fromBuffer(buf_sha256); + while (true) { + ecsignature = ecdsa.sign(secp256k1, buf_sha256, private_key.d, nonce++); + der = ecsignature.toDER(); + lenR = der[3]; + lenS = der[5 + lenR]; + if (lenR === 32 && lenS === 32) { + i = ecdsa.calcPubKeyRecoveryParam(secp256k1, e, ecsignature, private_key.toPublicKey().Q); + i += 4; // compressed + i += 27; // compact // 24 or 27 :( forcing odd-y 2nd key candidate) + break; + } + if (nonce % 10 === 0) { + console.log("WARN: " + nonce + " attempts to find canonical signature"); + } + } + return new Signature(ecsignature.r, ecsignature.s, i); + } + }, { + key: 'sign', + value: function sign(string, private_key) { + return Signature.signBuffer(new Buffer(string), private_key); + } + }, { + key: 'fromHex', + value: function fromHex(hex) { + return Signature.fromBuffer(new Buffer(hex, "hex")); + } + }, { + key: 'signHex', + value: function signHex(hex, private_key) { + var buf; + buf = new Buffer(hex, 'hex'); + return Signature.signBuffer(buf, private_key); + } + }]); + + return Signature; +}(); + +module.exports = Signature; \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..88076da --- /dev/null +++ b/dist/index.js @@ -0,0 +1,3 @@ +"use strict"; + +module.exports = Object.assign(require("./chain"), require("./ecc"), require("./serializer")); \ No newline at end of file diff --git a/dist/serializer/index.js b/dist/serializer/index.js new file mode 100644 index 0000000..2059055 --- /dev/null +++ b/dist/serializer/index.js @@ -0,0 +1,22 @@ +'use strict'; + +module.exports = { + + // Primary class for creating operations + Serializer: require('./src/serializer'), + + // helper functions for creating operations + fp: require('./src/FastParser'), + + // Low level types + types: require('./src/types'), + + // Higher level operations (made out of generic types) + ops: require('./src/operations'), + + // Utility that generates JSON examples + template: require('./src/template'), + + // Serializer validation + SerializerValidation: require('./src/SerializerValidation') +}; \ No newline at end of file diff --git a/dist/serializer/src/FastParser.js b/dist/serializer/src/FastParser.js new file mode 100644 index 0000000..ee30cf4 --- /dev/null +++ b/dist/serializer/src/FastParser.js @@ -0,0 +1,90 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var PublicKey = require("../../ecc/src/PublicKey"); + +var FastParser = function () { + function FastParser() { + _classCallCheck(this, FastParser); + } + + _createClass(FastParser, null, [{ + key: 'fixed_data', + value: function fixed_data(b, len, buffer) { + if (!b) { + return; + } + if (buffer) { + var data = buffer.slice(0, len).toString('binary'); + b.append(data, 'binary'); + while (len-- > data.length) { + b.writeUint8(0); + } + } else { + var b_copy = b.copy(b.offset, b.offset + len); + b.skip(len); + return new Buffer(b_copy.toBinary(), 'binary'); + } + } + }, { + key: 'public_key', + value: function public_key(b, _public_key) { + if (!b) { + return; + } + if (_public_key) { + var buffer = _public_key.toBuffer(); + b.append(buffer.toString('binary'), 'binary'); + return; + } else { + buffer = FastParser.fixed_data(b, 33); + return PublicKey.fromBuffer(buffer); + } + } + }, { + key: 'ripemd160', + value: function ripemd160(b, _ripemd) { + if (!b) { + return; + } + if (_ripemd) { + FastParser.fixed_data(b, 20, _ripemd); + return; + } else { + return FastParser.fixed_data(b, 20); + } + } + }, { + key: 'sha256', + value: function sha256(b, _sha) { + if (!b) { + return; + } + if (_sha) { + FastParser.fixed_data(b, 32, _sha); + return; + } else { + return FastParser.fixed_data(b, 32); + } + } + }, { + key: 'time_point_sec', + value: function time_point_sec(b, epoch) { + if (epoch) { + epoch = Math.ceil(epoch / 1000); + b.writeInt32(epoch); + return; + } else { + epoch = b.readInt32(); // fc::time_point_sec + return new Date(epoch * 1000); + } + } + }]); + + return FastParser; +}(); + +module.exports = FastParser; \ No newline at end of file diff --git a/dist/serializer/src/SerializerValidation.js b/dist/serializer/src/SerializerValidation.js new file mode 100644 index 0000000..334d8c7 --- /dev/null +++ b/dist/serializer/src/SerializerValidation.js @@ -0,0 +1,363 @@ +'use strict'; + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +var _require = require('bytebuffer'), + Long = _require.Long; + +var ChainTypes = require('../../chain/src/ChainTypes'); + +var MAX_SAFE_INT = 9007199254740991; +var MIN_SAFE_INT = -9007199254740991; + +/** + Most validations are skipped and the value returned unchanged when an empty string, null, or undefined is encountered (except "required"). + + Validations support a string format for dealing with large numbers. +*/ +var _my = { + + is_empty: function is_empty(value) { + return value === null || value === undefined; + }, + + required: function required(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + throw new Error('value required ' + field_name + ' ' + value); + } + return value; + }, + require_long: function require_long(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (!Long.isLong(value)) { + throw new Error('Long value required ' + field_name + ' ' + value); + } + return value; + }, + string: function string(value) { + if (this.is_empty(value)) { + return value; + } + if (typeof value !== "string") { + throw new Error('string required: ' + value); + } + return value; + }, + number: function number(value) { + if (this.is_empty(value)) { + return value; + } + if (typeof value !== "number") { + throw new Error('number required: ' + value); + } + return value; + }, + whole_number: function whole_number(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (/\./.test(value)) { + throw new Error('whole number required ' + field_name + ' ' + value); + } + return value; + }, + unsigned: function unsigned(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (/-/.test(value)) { + throw new Error('unsigned required ' + field_name + ' ' + value); + } + return value; + }, + + + is_digits: function is_digits(value) { + if (typeof value === "numeric") { + return true; + } + return (/^[0-9]+$/.test(value) + ); + }, + + to_number: function to_number(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + this.no_overflow53(value, field_name); + var int_value = function () { + if (typeof value === "number") { + return value; + } else { + return parseInt(value); + } + }(); + return int_value; + }, + + to_long: function to_long(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (Long.isLong(value)) { + return value; + } + + this.no_overflow64(value, field_name); + if (typeof value === "number") { + value = "" + value; + } + return Long.fromString(value); + }, + to_ulong: function to_ulong(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (Long.isLong(value)) { + return value; + } + + this.no_overflow64(value, field_name, true); + if (typeof value === "number") { + value = "" + value; + } + return Long.fromString(value, true); + }, + to_string: function to_string(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (this.is_empty(value)) { + return value; + } + if (typeof value === "string") { + return value; + } + if (typeof value === "number") { + this.no_overflow53(value, field_name); + return "" + value; + } + if (Long.isLong(value)) { + return value.toString(); + } + throw 'unsupported type ' + field_name + ': (' + (typeof value === 'undefined' ? 'undefined' : _typeof(value)) + ') ' + value; + }, + require_test: function require_test(regex, value) { + var field_name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; + + if (this.is_empty(value)) { + return value; + } + if (!regex.test(value)) { + throw new Error('unmatched ' + regex + ' ' + field_name + ' ' + value); + } + return value; + }, + + + require_match: function require_match(regex, value) { + var field_name = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; + + if (this.is_empty(value)) { + return value; + } + var match = value.match(regex); + if (match === null) { + throw new Error('unmatched ' + regex + ' ' + field_name + ' ' + value); + } + return match; + }, + + require_object_id: function require_object_id(value, field_name) { + return require_match(/^([0-9]+)\.([0-9]+)\.([0-9]+)$/, value, field_name); + }, + + // Does not support over 53 bits + require_range: function require_range(min, max, value) { + var field_name = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ""; + + if (this.is_empty(value)) { + return value; + } + var number = this.to_number(value); + if (value < min || value > max) { + throw new Error('out of range ' + value + ' ' + field_name + ' ' + value); + } + return value; + }, + + + require_object_type: function require_object_type() { + var reserved_spaces = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; + var type = arguments[1]; + var value = arguments[2]; + var field_name = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ""; + + if (this.is_empty(value)) { + return value; + } + var object_type = ChainTypes.object_type[type]; + if (!object_type) { + throw new Error('Unknown object type ' + type + ' ' + field_name + ' ' + value); + } + var re = new RegExp(reserved_spaces + '.' + object_type + '.[0-9]+$'); + if (!re.test(value)) { + throw new Error('Expecting ' + type + ' in format ' + (reserved_spaces + '.' + object_type + '.[0-9]+ ') + ('instead of ' + value + ' ' + field_name + ' ' + value)); + } + return value; + }, + + get_instance: function get_instance(reserve_spaces, type, value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_type(reserve_spaces, type, value, field_name); + return this.to_number(value.split('.')[2]); + }, + + require_relative_type: function require_relative_type(type, value, field_name) { + this.require_object_type(0, type, value, field_name); + return value; + }, + + get_relative_instance: function get_relative_instance(type, value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_type(0, type, value, field_name); + return this.to_number(value.split('.')[2]); + }, + + require_protocol_type: function require_protocol_type(type, value, field_name) { + this.require_object_type(1, type, value, field_name); + return value; + }, + + get_protocol_instance: function get_protocol_instance(type, value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_type(1, type, value, field_name); + return this.to_number(value.split('.')[2]); + }, + + get_protocol_type: function get_protocol_type(value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_id(value, field_name); + var values = value.split('.'); + return this.to_number(values[1]); + }, + + get_protocol_type_name: function get_protocol_type_name(value, field_name) { + if (this.is_empty(value)) { + return value; + } + var type_id = this.get_protocol_type(value, field_name); + return Object.keys(ChainTypes.object_type)[type_id]; + }, + + + require_implementation_type: function require_implementation_type(type, value, field_name) { + this.require_object_type(2, type, value, field_name); + return value; + }, + + get_implementation_instance: function get_implementation_instance(type, value, field_name) { + if (this.is_empty(value)) { + return value; + } + this.require_object_type(2, type, value, field_name); + return this.to_number(value.split('.')[2]); + }, + + // signed / unsigned decimal + no_overflow53: function no_overflow53(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + + if (typeof value === "number") { + if (value > MAX_SAFE_INT || value < MIN_SAFE_INT) { + throw new Error('overflow ' + field_name + ' ' + value); + } + return; + } + if (typeof value === "string") { + var int = parseInt(value); + if (value > MAX_SAFE_INT || value < MIN_SAFE_INT) { + throw new Error('overflow ' + field_name + ' ' + value); + } + return; + } + if (Long.isLong(value)) { + // typeof value.toInt() is 'number' + this.no_overflow53(value.toInt(), field_name); + return; + } + throw 'unsupported type ' + field_name + ': (' + (typeof value === 'undefined' ? 'undefined' : _typeof(value)) + ') ' + value; + }, + + + // signed / unsigned whole numbers only + no_overflow64: function no_overflow64(value) { + var field_name = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ""; + var unsigned = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; + + // https://github.com/dcodeIO/Long.js/issues/20 + if (Long.isLong(value)) { + return; + } + + // BigInteger#isBigInteger https://github.com/cryptocoinjs/bigi/issues/20 + if (value.t !== undefined && value.s !== undefined) { + this.no_overflow64(value.toString(), field_name, unsigned); + + return; + } + + if (typeof value === "string") { + // remove leading zeros, will cause a false positive + value = value.replace(/^0+/, ''); + // remove trailing zeros + while (/0$/.test(value)) { + value = value.substring(0, value.length - 1); + } + if (/\.$/.test(value)) { + // remove trailing dot + value = value.substring(0, value.length - 1); + } + if (value === "") { + value = "0"; + } + + var long_string = Long.fromString(value, unsigned).toString(); + + if (long_string !== value.trim()) { + throw new Error('overflow ' + field_name + ' ' + value); + } + return; + } + if (typeof value === "number") { + if (value > MAX_SAFE_INT || value < MIN_SAFE_INT) { + throw new Error('overflow ' + field_name + ' ' + value); + } + return; + } + + throw 'unsupported type ' + field_name + ': (' + (typeof value === 'undefined' ? 'undefined' : _typeof(value)) + ') ' + value; + } +}; + +module.exports = _my; \ No newline at end of file diff --git a/dist/serializer/src/convert.js b/dist/serializer/src/convert.js new file mode 100644 index 0000000..e9b43ef --- /dev/null +++ b/dist/serializer/src/convert.js @@ -0,0 +1,37 @@ +'use strict'; + +var ByteBuffer = require('bytebuffer'); + +module.exports = function (type) { + + return { + fromHex: function fromHex(hex) { + var b = ByteBuffer.fromHex(hex, ByteBuffer.LITTLE_ENDIAN); + return type.fromByteBuffer(b); + }, + toHex: function toHex(object) { + var b = toByteBuffer(type, object); + return b.toHex(); + }, + fromBuffer: function fromBuffer(buffer) { + var b = ByteBuffer.fromBinary(buffer.toString(), ByteBuffer.LITTLE_ENDIAN); + return type.fromByteBuffer(b); + }, + toBuffer: function toBuffer(object) { + return new Buffer(toByteBuffer(type, object).toBinary(), 'binary'); + }, + fromBinary: function fromBinary(string) { + var b = ByteBuffer.fromBinary(string, ByteBuffer.LITTLE_ENDIAN); + return type.fromByteBuffer(b); + }, + toBinary: function toBinary(object) { + return toByteBuffer(type, object).toBinary(); + } + }; +}; + +var toByteBuffer = function toByteBuffer(type, object) { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + type.appendByteBuffer(b, object); + return b.copy(0, b.offset); +}; \ No newline at end of file diff --git a/dist/serializer/src/error_with_cause.js b/dist/serializer/src/error_with_cause.js new file mode 100644 index 0000000..e36aa85 --- /dev/null +++ b/dist/serializer/src/error_with_cause.js @@ -0,0 +1,42 @@ +"use strict"; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +/** Exception nesting. */ +var ErrorWithCause = function () { + function ErrorWithCause(message, cause) { + _classCallCheck(this, ErrorWithCause); + + this.message = message; + if (typeof cause !== "undefined" && cause !== null ? cause.message : undefined) { + this.message = "cause\t" + cause.message + "\t" + this.message; + } + + var stack = ""; //(new Error).stack + if (typeof cause !== "undefined" && cause !== null ? cause.stack : undefined) { + stack = "caused by\n\t" + cause.stack + "\t" + stack; + } + + this.stack = this.message + "\n" + stack; + } + + _createClass(ErrorWithCause, null, [{ + key: "throw", + value: function _throw(message, cause) { + var msg = message; + if (typeof cause !== "undefined" && cause !== null ? cause.message : undefined) { + msg += "\t cause: " + cause.message + " "; + } + if (typeof cause !== "undefined" && cause !== null ? cause.stack : undefined) { + msg += "\n stack: " + cause.stack + " "; + } + throw new Error(msg); + } + }]); + + return ErrorWithCause; +}(); + +module.exports = ErrorWithCause; \ No newline at end of file diff --git a/dist/serializer/src/operations.js b/dist/serializer/src/operations.js new file mode 100644 index 0000000..1c82d8c --- /dev/null +++ b/dist/serializer/src/operations.js @@ -0,0 +1,709 @@ +"use strict"; + +var types = require("./types"); +var SerializerImpl = require("./serializer"); + +var uint8 = types.uint8, + uint16 = types.uint16, + uint32 = types.uint32, + int64 = types.int64, + uint64 = types.uint64, + string = types.string, + bytes = types.bytes, + bool = types.bool, + array = types.array, + fixed_array = types.fixed_array, + protocol_id_type = types.protocol_id_type, + object_id_type = types.object_id_type, + vote_id = types.vote_id, + future_extensions = types.future_extensions, + static_variant = types.static_variant, + map = types.map, + set = types.set, + public_key = types.public_key, + address = types.address, + time_point_sec = types.time_point_sec, + optional = types.optional, + variant = types.variant, + variant_object = types.variant_object, + enumeration = types.enumeration, + sha256 = types.sha256; + + +future_extensions = types.void; + +/* +When updating generated code +Replace: operation = static_variant [ +with: operation.st_operations = [ + +Delete: +public_key = new Serializer( + "public_key" + key_data: bytes 33 +) + +*/ +// Place-holder, their are dependencies on "operation" .. The final list of +// operations is not avialble until the very end of the generated code. +// See: operation.st_operations = ... +var operation = static_variant(); +module.exports["operation"] = operation; + +// For module.exports +var Serializer = function Serializer(operation_name, serilization_types_object) { + var s = new SerializerImpl(operation_name, serilization_types_object); + return module.exports[operation_name] = s; +}; + +// Custom-types follow Generated code: + +// ## Generated code follows +// # programs/js_operation_serializer > npm i -g decaffeinate +// ## ------------------------------- +var transfer_operation_fee_parameters = new Serializer("transfer_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var limit_order_create_operation_fee_parameters = new Serializer("limit_order_create_operation_fee_parameters", { fee: uint64 }); + +var limit_order_cancel_operation_fee_parameters = new Serializer("limit_order_cancel_operation_fee_parameters", { fee: uint64 }); + +var call_order_update_operation_fee_parameters = new Serializer("call_order_update_operation_fee_parameters", { fee: uint64 }); + +var fill_order_operation_fee_parameters = new Serializer("fill_order_operation_fee_parameters"); + +var account_create_operation_fee_parameters = new Serializer("account_create_operation_fee_parameters", { basic_fee: uint64, + premium_fee: uint64, + price_per_kbyte: uint32 }); + +var account_update_operation_fee_parameters = new Serializer("account_update_operation_fee_parameters", { fee: int64, + price_per_kbyte: uint32 }); + +var account_whitelist_operation_fee_parameters = new Serializer("account_whitelist_operation_fee_parameters", { fee: int64 }); + +var account_upgrade_operation_fee_parameters = new Serializer("account_upgrade_operation_fee_parameters", { membership_annual_fee: uint64, + membership_lifetime_fee: uint64 }); + +var account_transfer_operation_fee_parameters = new Serializer("account_transfer_operation_fee_parameters", { fee: uint64 }); + +var asset_create_operation_fee_parameters = new Serializer("asset_create_operation_fee_parameters", { symbol3: uint64, + symbol4: uint64, + long_symbol: uint64, + price_per_kbyte: uint32 }); + +var asset_update_operation_fee_parameters = new Serializer("asset_update_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var asset_update_bitasset_operation_fee_parameters = new Serializer("asset_update_bitasset_operation_fee_parameters", { fee: uint64 }); + +var asset_update_feed_producers_operation_fee_parameters = new Serializer("asset_update_feed_producers_operation_fee_parameters", { fee: uint64 }); + +var asset_issue_operation_fee_parameters = new Serializer("asset_issue_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var asset_reserve_operation_fee_parameters = new Serializer("asset_reserve_operation_fee_parameters", { fee: uint64 }); + +var asset_fund_fee_pool_operation_fee_parameters = new Serializer("asset_fund_fee_pool_operation_fee_parameters", { fee: uint64 }); + +var asset_settle_operation_fee_parameters = new Serializer("asset_settle_operation_fee_parameters", { fee: uint64 }); + +var asset_global_settle_operation_fee_parameters = new Serializer("asset_global_settle_operation_fee_parameters", { fee: uint64 }); + +var asset_publish_feed_operation_fee_parameters = new Serializer("asset_publish_feed_operation_fee_parameters", { fee: uint64 }); + +var witness_create_operation_fee_parameters = new Serializer("witness_create_operation_fee_parameters", { fee: uint64 }); + +var witness_update_operation_fee_parameters = new Serializer("witness_update_operation_fee_parameters", { fee: int64 }); + +var proposal_create_operation_fee_parameters = new Serializer("proposal_create_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var proposal_update_operation_fee_parameters = new Serializer("proposal_update_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var proposal_delete_operation_fee_parameters = new Serializer("proposal_delete_operation_fee_parameters", { fee: uint64 }); + +var withdraw_permission_create_operation_fee_parameters = new Serializer("withdraw_permission_create_operation_fee_parameters", { fee: uint64 }); + +var withdraw_permission_update_operation_fee_parameters = new Serializer("withdraw_permission_update_operation_fee_parameters", { fee: uint64 }); + +var withdraw_permission_claim_operation_fee_parameters = new Serializer("withdraw_permission_claim_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var withdraw_permission_delete_operation_fee_parameters = new Serializer("withdraw_permission_delete_operation_fee_parameters", { fee: uint64 }); + +var committee_member_create_operation_fee_parameters = new Serializer("committee_member_create_operation_fee_parameters", { fee: uint64 }); + +var committee_member_update_operation_fee_parameters = new Serializer("committee_member_update_operation_fee_parameters", { fee: uint64 }); + +var committee_member_update_global_parameters_operation_fee_parameters = new Serializer("committee_member_update_global_parameters_operation_fee_parameters", { fee: uint64 }); + +var vesting_balance_create_operation_fee_parameters = new Serializer("vesting_balance_create_operation_fee_parameters", { fee: uint64 }); + +var vesting_balance_withdraw_operation_fee_parameters = new Serializer("vesting_balance_withdraw_operation_fee_parameters", { fee: uint64 }); + +var worker_create_operation_fee_parameters = new Serializer("worker_create_operation_fee_parameters", { fee: uint64 }); + +var custom_operation_fee_parameters = new Serializer("custom_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var assert_operation_fee_parameters = new Serializer("assert_operation_fee_parameters", { fee: uint64 }); + +var balance_claim_operation_fee_parameters = new Serializer("balance_claim_operation_fee_parameters"); + +var override_transfer_operation_fee_parameters = new Serializer("override_transfer_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var transfer_to_blind_operation_fee_parameters = new Serializer("transfer_to_blind_operation_fee_parameters", { fee: uint64, + price_per_output: uint32 }); + +var blind_transfer_operation_fee_parameters = new Serializer("blind_transfer_operation_fee_parameters", { fee: uint64, + price_per_output: uint32 }); + +var transfer_from_blind_operation_fee_parameters = new Serializer("transfer_from_blind_operation_fee_parameters", { fee: uint64 }); + +var asset_settle_cancel_operation_fee_parameters = new Serializer("asset_settle_cancel_operation_fee_parameters"); + +var asset_claim_fees_operation_fee_parameters = new Serializer("asset_claim_fees_operation_fee_parameters", { fee: uint64 }); + +var fba_distribute_operation_fee_parameters = new Serializer("fba_distribute_operation_fee_parameters", {}); + +var tournament_create_operation_fee_parameters = new Serializer("tournament_create_operation_fee_parameters", { fee: uint64, + price_per_kbyte: uint32 }); + +var tournament_join_operation_fee_parameters = new Serializer("tournament_join_operation_fee_parameters", { fee: uint64 }); + +var fee_parameters = static_variant([transfer_operation_fee_parameters, limit_order_create_operation_fee_parameters, limit_order_cancel_operation_fee_parameters, call_order_update_operation_fee_parameters, fill_order_operation_fee_parameters, account_create_operation_fee_parameters, account_update_operation_fee_parameters, account_whitelist_operation_fee_parameters, account_upgrade_operation_fee_parameters, account_transfer_operation_fee_parameters, asset_create_operation_fee_parameters, asset_update_operation_fee_parameters, asset_update_bitasset_operation_fee_parameters, asset_update_feed_producers_operation_fee_parameters, asset_issue_operation_fee_parameters, asset_reserve_operation_fee_parameters, asset_fund_fee_pool_operation_fee_parameters, asset_settle_operation_fee_parameters, asset_global_settle_operation_fee_parameters, asset_publish_feed_operation_fee_parameters, witness_create_operation_fee_parameters, witness_update_operation_fee_parameters, proposal_create_operation_fee_parameters, proposal_update_operation_fee_parameters, proposal_delete_operation_fee_parameters, withdraw_permission_create_operation_fee_parameters, withdraw_permission_update_operation_fee_parameters, withdraw_permission_claim_operation_fee_parameters, withdraw_permission_delete_operation_fee_parameters, committee_member_create_operation_fee_parameters, committee_member_update_operation_fee_parameters, committee_member_update_global_parameters_operation_fee_parameters, vesting_balance_create_operation_fee_parameters, vesting_balance_withdraw_operation_fee_parameters, worker_create_operation_fee_parameters, custom_operation_fee_parameters, assert_operation_fee_parameters, balance_claim_operation_fee_parameters, override_transfer_operation_fee_parameters, transfer_to_blind_operation_fee_parameters, blind_transfer_operation_fee_parameters, transfer_from_blind_operation_fee_parameters, asset_settle_cancel_operation_fee_parameters, asset_claim_fees_operation_fee_parameters, fba_distribute_operation_fee_parameters, tournament_create_operation_fee_parameters, tournament_join_operation_fee_parameters]); + +var fee_schedule = new Serializer("fee_schedule", { parameters: set(fee_parameters), + scale: uint32 }); + +var void_result = new Serializer("void_result"); + +var asset = new Serializer("asset", { amount: int64, + asset_id: protocol_id_type("asset") }); + +var operation_result = static_variant([void_result, object_id_type, asset]); + +var processed_transaction = new Serializer("processed_transaction", { ref_block_num: uint16, + ref_block_prefix: uint32, + expiration: time_point_sec, + operations: array(operation), + extensions: set(future_extensions), + signatures: array(bytes(65)), + operation_results: array(operation_result) }); + +var signed_block = new Serializer("signed_block", { previous: bytes(20), + timestamp: time_point_sec, + witness: protocol_id_type("witness"), + transaction_merkle_root: bytes(20), + extensions: set(future_extensions), + witness_signature: bytes(65), + transactions: array(processed_transaction) }); + +var block_header = new Serializer("block_header", { previous: bytes(20), + timestamp: time_point_sec, + witness: protocol_id_type("witness"), + transaction_merkle_root: bytes(20), + extensions: set(future_extensions) }); + +var signed_block_header = new Serializer("signed_block_header", { previous: bytes(20), + timestamp: time_point_sec, + witness: protocol_id_type("witness"), + transaction_merkle_root: bytes(20), + extensions: set(future_extensions), + witness_signature: bytes(65) }); + +var memo_data = new Serializer("memo_data", { from: public_key, + to: public_key, + nonce: uint64, + message: bytes() }); + +var transfer = new Serializer("transfer", { fee: asset, + from: protocol_id_type("account"), + to: protocol_id_type("account"), + amount: asset, + memo: optional(memo_data), + extensions: set(future_extensions) }); + +var limit_order_create = new Serializer("limit_order_create", { fee: asset, + seller: protocol_id_type("account"), + amount_to_sell: asset, + min_to_receive: asset, + expiration: time_point_sec, + fill_or_kill: bool, + extensions: set(future_extensions) }); + +var limit_order_cancel = new Serializer("limit_order_cancel", { fee: asset, + fee_paying_account: protocol_id_type("account"), + order: protocol_id_type("limit_order"), + extensions: set(future_extensions) }); + +var call_order_update = new Serializer("call_order_update", { fee: asset, + funding_account: protocol_id_type("account"), + delta_collateral: asset, + delta_debt: asset, + extensions: set(future_extensions) }); + +var fill_order = new Serializer("fill_order", { fee: asset, + order_id: object_id_type, + account_id: protocol_id_type("account"), + pays: asset, + receives: asset }); + +var authority = new Serializer("authority", { weight_threshold: uint32, + account_auths: map(protocol_id_type("account"), uint16), + key_auths: map(public_key, uint16), + address_auths: map(address, uint16) }); + +var account_options = new Serializer("account_options", { memo_key: public_key, + voting_account: protocol_id_type("account"), + num_witness: uint16, + num_committee: uint16, + votes: set(vote_id), + extensions: set(future_extensions) }); + +var account_create = new Serializer("account_create", { fee: asset, + registrar: protocol_id_type("account"), + referrer: protocol_id_type("account"), + referrer_percent: uint16, + name: string, + owner: authority, + active: authority, + options: account_options, + extensions: set(future_extensions) }); + +var account_update = new Serializer("account_update", { fee: asset, + account: protocol_id_type("account"), + owner: optional(authority), + active: optional(authority), + new_options: optional(account_options), + extensions: set(future_extensions) }); + +var account_whitelist = new Serializer("account_whitelist", { fee: asset, + authorizing_account: protocol_id_type("account"), + account_to_list: protocol_id_type("account"), + new_listing: uint8, + extensions: set(future_extensions) }); + +var account_upgrade = new Serializer("account_upgrade", { fee: asset, + account_to_upgrade: protocol_id_type("account"), + upgrade_to_lifetime_member: bool, + extensions: set(future_extensions) }); + +var account_transfer = new Serializer("account_transfer", { fee: asset, + account_id: protocol_id_type("account"), + new_owner: protocol_id_type("account"), + extensions: set(future_extensions) }); + +var price = new Serializer("price", { base: asset, + quote: asset }); + +var asset_options = new Serializer("asset_options", { max_supply: int64, + market_fee_percent: uint16, + max_market_fee: int64, + issuer_permissions: uint16, + flags: uint16, + core_exchange_rate: price, + whitelist_authorities: set(protocol_id_type("account")), + blacklist_authorities: set(protocol_id_type("account")), + whitelist_markets: set(protocol_id_type("asset")), + blacklist_markets: set(protocol_id_type("asset")), + description: string, + extensions: set(future_extensions) }); + +var bitasset_options = new Serializer("bitasset_options", { feed_lifetime_sec: uint32, + minimum_feeds: uint8, + force_settlement_delay_sec: uint32, + force_settlement_offset_percent: uint16, + maximum_force_settlement_volume: uint16, + short_backing_asset: protocol_id_type("asset"), + extensions: set(future_extensions) }); + +var asset_create = new Serializer("asset_create", { fee: asset, + issuer: protocol_id_type("account"), + symbol: string, + precision: uint8, + common_options: asset_options, + bitasset_opts: optional(bitasset_options), + is_prediction_market: bool, + extensions: set(future_extensions) }); + +var asset_update = new Serializer("asset_update", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_update: protocol_id_type("asset"), + new_issuer: optional(protocol_id_type("account")), + new_options: asset_options, + extensions: set(future_extensions) }); + +var asset_update_bitasset = new Serializer("asset_update_bitasset", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_update: protocol_id_type("asset"), + new_options: bitasset_options, + extensions: set(future_extensions) }); + +var asset_update_feed_producers = new Serializer("asset_update_feed_producers", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_update: protocol_id_type("asset"), + new_feed_producers: set(protocol_id_type("account")), + extensions: set(future_extensions) }); + +var asset_issue = new Serializer("asset_issue", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_issue: asset, + issue_to_account: protocol_id_type("account"), + memo: optional(memo_data), + extensions: set(future_extensions) }); + +var asset_reserve = new Serializer("asset_reserve", { fee: asset, + payer: protocol_id_type("account"), + amount_to_reserve: asset, + extensions: set(future_extensions) }); + +var asset_fund_fee_pool = new Serializer("asset_fund_fee_pool", { fee: asset, + from_account: protocol_id_type("account"), + asset_id: protocol_id_type("asset"), + amount: int64, + extensions: set(future_extensions) }); + +var asset_settle = new Serializer("asset_settle", { fee: asset, + account: protocol_id_type("account"), + amount: asset, + extensions: set(future_extensions) }); + +var asset_global_settle = new Serializer("asset_global_settle", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_settle: protocol_id_type("asset"), + settle_price: price, + extensions: set(future_extensions) }); + +var price_feed = new Serializer("price_feed", { settlement_price: price, + maintenance_collateral_ratio: uint16, + maximum_short_squeeze_ratio: uint16, + core_exchange_rate: price }); + +var asset_publish_feed = new Serializer("asset_publish_feed", { fee: asset, + publisher: protocol_id_type("account"), + asset_id: protocol_id_type("asset"), + feed: price_feed, + extensions: set(future_extensions) }); + +var witness_create = new Serializer("witness_create", { fee: asset, + witness_account: protocol_id_type("account"), + url: string, + block_signing_key: public_key }); + +var witness_update = new Serializer("witness_update", { fee: asset, + witness: protocol_id_type("witness"), + witness_account: protocol_id_type("account"), + new_url: optional(string), + new_signing_key: optional(public_key) }); + +var op_wrapper = new Serializer("op_wrapper", { op: operation }); + +var proposal_create = new Serializer("proposal_create", { fee: asset, + fee_paying_account: protocol_id_type("account"), + expiration_time: time_point_sec, + proposed_ops: array(op_wrapper), + review_period_seconds: optional(uint32), + extensions: set(future_extensions) }); + +var proposal_update = new Serializer("proposal_update", { fee: asset, + fee_paying_account: protocol_id_type("account"), + proposal: protocol_id_type("proposal"), + active_approvals_to_add: set(protocol_id_type("account")), + active_approvals_to_remove: set(protocol_id_type("account")), + owner_approvals_to_add: set(protocol_id_type("account")), + owner_approvals_to_remove: set(protocol_id_type("account")), + key_approvals_to_add: set(public_key), + key_approvals_to_remove: set(public_key), + extensions: set(future_extensions) }); + +var proposal_delete = new Serializer("proposal_delete", { fee: asset, + fee_paying_account: protocol_id_type("account"), + using_owner_authority: bool, + proposal: protocol_id_type("proposal"), + extensions: set(future_extensions) }); + +var withdraw_permission_create = new Serializer("withdraw_permission_create", { fee: asset, + withdraw_from_account: protocol_id_type("account"), + authorized_account: protocol_id_type("account"), + withdrawal_limit: asset, + withdrawal_period_sec: uint32, + periods_until_expiration: uint32, + period_start_time: time_point_sec }); + +var withdraw_permission_update = new Serializer("withdraw_permission_update", { fee: asset, + withdraw_from_account: protocol_id_type("account"), + authorized_account: protocol_id_type("account"), + permission_to_update: protocol_id_type("withdraw_permission"), + withdrawal_limit: asset, + withdrawal_period_sec: uint32, + period_start_time: time_point_sec, + periods_until_expiration: uint32 }); + +var withdraw_permission_claim = new Serializer("withdraw_permission_claim", { fee: asset, + withdraw_permission: protocol_id_type("withdraw_permission"), + withdraw_from_account: protocol_id_type("account"), + withdraw_to_account: protocol_id_type("account"), + amount_to_withdraw: asset, + memo: optional(memo_data) }); + +var withdraw_permission_delete = new Serializer("withdraw_permission_delete", { fee: asset, + withdraw_from_account: protocol_id_type("account"), + authorized_account: protocol_id_type("account"), + withdrawal_permission: protocol_id_type("withdraw_permission") }); + +var committee_member_create = new Serializer("committee_member_create", { fee: asset, + committee_member_account: protocol_id_type("account"), + url: string }); + +var committee_member_update = new Serializer("committee_member_update", { fee: asset, + committee_member: protocol_id_type("committee_member"), + committee_member_account: protocol_id_type("account"), + new_url: optional(string) }); + +var chain_parameters = new Serializer("chain_parameters", { current_fees: fee_schedule, + block_interval: uint8, + maintenance_interval: uint32, + maintenance_skip_slots: uint8, + committee_proposal_review_period: uint32, + maximum_transaction_size: uint32, + maximum_block_size: uint32, + maximum_time_until_expiration: uint32, + maximum_proposal_lifetime: uint32, + maximum_asset_whitelist_authorities: uint8, + maximum_asset_feed_publishers: uint8, + maximum_witness_count: uint16, + maximum_committee_count: uint16, + maximum_authority_membership: uint16, + reserve_percent_of_fee: uint16, + network_percent_of_fee: uint16, + lifetime_referrer_percent_of_fee: uint16, + cashback_vesting_period_seconds: uint32, + cashback_vesting_threshold: int64, + count_non_member_votes: bool, + allow_non_member_whitelists: bool, + witness_pay_per_block: int64, + worker_budget_per_day: int64, + max_predicate_opcode: uint16, + fee_liquidation_threshold: int64, + accounts_per_fee_scale: uint16, + account_fee_scale_bitshifts: uint8, + max_authority_depth: uint8, + extensions: set(future_extensions) }); + +var committee_member_update_global_parameters = new Serializer("committee_member_update_global_parameters", { fee: asset, + new_parameters: chain_parameters }); + +var linear_vesting_policy_initializer = new Serializer("linear_vesting_policy_initializer", { begin_timestamp: time_point_sec, + vesting_cliff_seconds: uint32, + vesting_duration_seconds: uint32 }); + +var cdd_vesting_policy_initializer = new Serializer("cdd_vesting_policy_initializer", { start_claim: time_point_sec, + vesting_seconds: uint32 }); + +var vesting_policy_initializer = static_variant([linear_vesting_policy_initializer, cdd_vesting_policy_initializer]); + +var vesting_balance_create = new Serializer("vesting_balance_create", { fee: asset, + creator: protocol_id_type("account"), + owner: protocol_id_type("account"), + amount: asset, + policy: vesting_policy_initializer }); + +var vesting_balance_withdraw = new Serializer("vesting_balance_withdraw", { fee: asset, + vesting_balance: protocol_id_type("vesting_balance"), + owner: protocol_id_type("account"), + amount: asset }); + +var refund_worker_initializer = new Serializer("refund_worker_initializer"); + +var vesting_balance_worker_initializer = new Serializer("vesting_balance_worker_initializer", { pay_vesting_period_days: uint16 }); + +var burn_worker_initializer = new Serializer("burn_worker_initializer"); + +var worker_initializer = static_variant([refund_worker_initializer, vesting_balance_worker_initializer, burn_worker_initializer]); + +var worker_create = new Serializer("worker_create", { fee: asset, + owner: protocol_id_type("account"), + work_begin_date: time_point_sec, + work_end_date: time_point_sec, + daily_pay: int64, + name: string, + url: string, + initializer: worker_initializer }); + +var custom = new Serializer("custom", { fee: asset, + payer: protocol_id_type("account"), + required_auths: set(protocol_id_type("account")), + id: uint16, + data: bytes() }); + +var account_name_eq_lit_predicate = new Serializer("account_name_eq_lit_predicate", { account_id: protocol_id_type("account"), + name: string }); + +var asset_symbol_eq_lit_predicate = new Serializer("asset_symbol_eq_lit_predicate", { asset_id: protocol_id_type("asset"), + symbol: string }); + +var block_id_predicate = new Serializer("block_id_predicate", { id: bytes(20) }); + +var predicate = static_variant([account_name_eq_lit_predicate, asset_symbol_eq_lit_predicate, block_id_predicate]); + +var assert = new Serializer("assert", { fee: asset, + fee_paying_account: protocol_id_type("account"), + predicates: array(predicate), + required_auths: set(protocol_id_type("account")), + extensions: set(future_extensions) }); + +var balance_claim = new Serializer("balance_claim", { fee: asset, + deposit_to_account: protocol_id_type("account"), + balance_to_claim: protocol_id_type("balance"), + balance_owner_key: public_key, + total_claimed: asset }); + +var override_transfer = new Serializer("override_transfer", { fee: asset, + issuer: protocol_id_type("account"), + from: protocol_id_type("account"), + to: protocol_id_type("account"), + amount: asset, + memo: optional(memo_data), + extensions: set(future_extensions) }); + +var stealth_confirmation = new Serializer("stealth_confirmation", { one_time_key: public_key, + to: optional(public_key), + encrypted_memo: bytes() }); + +var blind_output = new Serializer("blind_output", { commitment: bytes(33), + range_proof: bytes(), + owner: authority, + stealth_memo: optional(stealth_confirmation) }); + +var transfer_to_blind = new Serializer("transfer_to_blind", { fee: asset, + amount: asset, + from: protocol_id_type("account"), + blinding_factor: bytes(32), + outputs: array(blind_output) }); + +var blind_input = new Serializer("blind_input", { commitment: bytes(33), + owner: authority }); + +var blind_transfer = new Serializer("blind_transfer", { fee: asset, + inputs: array(blind_input), + outputs: array(blind_output) }); + +var transfer_from_blind = new Serializer("transfer_from_blind", { fee: asset, + amount: asset, + to: protocol_id_type("account"), + blinding_factor: bytes(32), + inputs: array(blind_input) }); + +var asset_settle_cancel = new Serializer("asset_settle_cancel", { fee: asset, + settlement: protocol_id_type("force_settlement"), + account: protocol_id_type("account"), + amount: asset, + extensions: set(future_extensions) }); + +var asset_claim_fees = new Serializer("asset_claim_fees", { fee: asset, + issuer: protocol_id_type("account"), + amount_to_claim: asset, + extensions: set(future_extensions) }); + +var fba_distribute = new Serializer("fba_distribute", { fee: asset, + account_id: protocol_id_type("account"), + fba_id: protocol_id_type("fba_accumulator"), + amount: int64 }); + +var dividend_asset_options = new Serializer("dividend_asset_options", { next_payout_time: optional(time_point_sec), + payout_interval: optional(uint32), + minimum_fee_percentage: uint64, + minimum_distribution_interval: optional(uint32), + extensions: set(future_extensions) }); + +var asset_update_dividend = new Serializer("asset_update_dividend", { fee: asset, + issuer: protocol_id_type("account"), + asset_to_update: protocol_id_type("asset"), + new_options: dividend_asset_options, + extensions: set(future_extensions) }); + +var rock_paper_scissors_game_options = new Serializer("rock_paper_scissors_game_options", { insurance_enabled: bool, + time_per_commit_move: uint32, + time_per_reveal_move: uint32, + number_of_gestures: uint8 }); + +var game_specific_details = static_variant([rock_paper_scissors_game_options]); + +var tournament_options = new Serializer("tournament_options", { + type_of_game: uint16, + registration_deadline: time_point_sec, + number_of_players: uint32, + buy_in: asset, + whitelist: set(protocol_id_type("account")), + start_time: optional(time_point_sec), + start_delay: optional(uint32), + round_delay: uint32, + number_of_wins: uint32, + meta: variant_object, + game_options: game_specific_details +}); + +var tournament_create = new Serializer("tournament_create", { fee: asset, + creator: protocol_id_type("account"), + options: tournament_options, + extensions: set(future_extensions) }); + +var tournament_join = new Serializer("tournament_join", { fee: asset, + payer_account_id: protocol_id_type("account"), + player_account_id: protocol_id_type("account"), + tournament_id: protocol_id_type("tournament"), + buy_in: asset, + extensions: set(future_extensions) }); + +var rock_paper_scissors_gesture = enumeration(["rock", "paper", "scissors", "spock", "lizard"]); + +var rock_paper_scissors_throw_commit = new Serializer("rock_paper_scissors_throw_commit", { nonce1: uint64, + throw_hash: sha256 }); + +var rock_paper_scissors_throw_reveal = new Serializer("rock_paper_scissors_throw_reveal", { nonce2: uint64, + gesture: rock_paper_scissors_gesture }); + +var game_specific_moves = static_variant([rock_paper_scissors_throw_commit, rock_paper_scissors_throw_reveal]); + +var game_move = new Serializer("game_move", { fee: asset, + game_id: protocol_id_type("game"), + player_account_id: protocol_id_type("account"), + move: game_specific_moves, + extensions: set(future_extensions) }); + +operation.st_operations = [transfer, limit_order_create, limit_order_cancel, call_order_update, fill_order, account_create, account_update, account_whitelist, account_upgrade, account_transfer, asset_create, asset_update, asset_update_bitasset, asset_update_feed_producers, asset_issue, asset_reserve, asset_fund_fee_pool, asset_settle, asset_global_settle, asset_publish_feed, witness_create, witness_update, proposal_create, proposal_update, proposal_delete, withdraw_permission_create, withdraw_permission_update, withdraw_permission_claim, withdraw_permission_delete, committee_member_create, committee_member_update, committee_member_update_global_parameters, vesting_balance_create, vesting_balance_withdraw, worker_create, custom, assert, balance_claim, override_transfer, transfer_to_blind, blind_transfer, transfer_from_blind, asset_settle_cancel, asset_claim_fees, fba_distribute, tournament_create, tournament_join, game_move, asset_update_dividend]; + +var transaction = new Serializer("transaction", { ref_block_num: uint16, + ref_block_prefix: uint32, + expiration: time_point_sec, + operations: array(operation), + extensions: set(future_extensions) }); + +var signed_transaction = new Serializer("signed_transaction", { ref_block_num: uint16, + ref_block_prefix: uint32, + expiration: time_point_sec, + operations: array(operation), + extensions: set(future_extensions), + signatures: array(bytes(65)) }); +//# ------------------------------- +//# Generated code end +//# ------------------------------- + +// Custom Types + +var stealth_memo_data = new Serializer("stealth_memo_data", { + from: optional(public_key), + amount: asset, + blinding_factor: bytes(32), + commitment: bytes(33), + check: uint32 +}); +// var stealth_confirmation = new Serializer( +// "stealth_confirmation", { +// one_time_key: public_key, +// to: optional( public_key ), +// encrypted_memo: stealth_memo_data +// }) \ No newline at end of file diff --git a/dist/serializer/src/precision.js b/dist/serializer/src/precision.js new file mode 100644 index 0000000..81e7ab3 --- /dev/null +++ b/dist/serializer/src/precision.js @@ -0,0 +1,95 @@ +'use strict'; + +var _my; +var _internal; +var v = require('./SerializerValidation'); +var BigInteger = require('bigi'); + +module.exports = _my = + +// Result may be used for int64 types (like transfer amount). Asset's +// precision is used to convert the number to a whole number with an implied +// decimal place. + +// "1.01" with a precision of 2 returns long 101 +// See http://cryptocoinjs.com/modules/misc/bigi/#example +{ + to_bigint64: function to_bigint64(number_or_string, precision) { + var error_info = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; + + var long = _internal.to_long64(number_or_string, precision, error_info); + return BigInteger(long.toString()); + }, + + + // 101 string or long with a precision of 2 returns "1.01" + to_string64: function to_string64(number_or_string, precision) { + var error_info = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; + + v.required(number_or_string, error_info); + v.number(precision, error_info); + var number_long = v.to_long(number_or_string, error_info); + var string64 = _internal.decimal_precision_string(number_long, precision, error_info); + v.no_overflow64(string64, error_info); + return string64; + } +}; + +// _internal is for low-level transaction code +module.exports._internal = _internal = + +// Warning: Long operations may over-flow without detection +{ + to_long64: function to_long64(number_or_string, precision) { + var error_info = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; + + v.required(number_or_string, "number_or_string " + error_info); + v.required(precision, "precision " + error_info); + return v.to_long(_internal.decimal_precision_string(number_or_string, precision, error_info)); + }, + decimal_precision_string: function decimal_precision_string(number, precision) { + var error_info = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : ""; + + v.required(number, "number " + error_info); + v.required(precision, "precision " + error_info); + + var number_string = v.to_string(number); + number_string = number_string.trim(); + precision = v.to_number(precision); + + // remove leading zeros (not suffixing) + var number_parts = number_string.match(/^-?0*([0-9]*)\.?([0-9]*)$/); + if (!number_parts) { + throw new Error('Invalid number: ' + number_string + ' ' + error_info); + } + + var sign = number_string.charAt(0) === '-' ? '-' : ''; + var int_part = number_parts[1]; + var decimal_part = number_parts[2]; + if (!decimal_part) { + decimal_part = ""; + } + + // remove trailing zeros + while (/0$/.test(decimal_part)) { + decimal_part = decimal_part.substring(0, decimal_part.length - 1); + } + + var zero_pad_count = precision - decimal_part.length; + if (zero_pad_count < 0) { + throw new Error('overflow, up to ' + precision + ' decimals may be used ' + error_info); + } + + if (sign === "-" && !/[1-9]/.test(int_part + decimal_part)) { + sign = ""; + } + if (int_part === "") { + int_part = "0"; + } + for (var i = 0; 0 < zero_pad_count ? i < zero_pad_count : i > zero_pad_count; 0 < zero_pad_count ? i++ : i++) { + decimal_part += "0"; + } + + return sign + int_part + decimal_part; + } +}; \ No newline at end of file diff --git a/dist/serializer/src/serializer.js b/dist/serializer/src/serializer.js new file mode 100644 index 0000000..161ca14 --- /dev/null +++ b/dist/serializer/src/serializer.js @@ -0,0 +1,207 @@ +'use strict'; + +var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var ByteBuffer = require('bytebuffer'); +var EC = require('./error_with_cause'); + +var HEX_DUMP = process.env.npm_config__graphene_serializer_hex_dump; + +var Serializer = function () { + function Serializer(operation_name, types) { + _classCallCheck(this, Serializer); + + this.operation_name = operation_name; + this.types = types; + if (this.types) this.keys = Object.keys(this.types); + + Serializer.printDebug = true; + } + + _createClass(Serializer, [{ + key: 'fromByteBuffer', + value: function fromByteBuffer(b) { + var object = {}; + var field = null; + try { + var iterable = this.keys; + for (var i = 0, field; i < iterable.length; i++) { + field = iterable[i]; + var type = this.types[field]; + try { + if (HEX_DUMP) { + if (type.operation_name) { + console.error(type.operation_name); + } else { + var o1 = b.offset; + type.fromByteBuffer(b); + var o2 = b.offset; + b.offset = o1; + //b.reset() + var _b = b.copy(o1, o2); + console.error(this.operation_name + '.' + field + '\t', _b.toHex()); + } + } + object[field] = type.fromByteBuffer(b); + } catch (e) { + if (Serializer.printDebug) { + console.error('Error reading ' + this.operation_name + '.' + field + ' in data:'); + b.printDebug(); + } + throw e; + } + } + } catch (error) { + EC.throw(this.operation_name + '.' + field, error); + } + + return object; + } + }, { + key: 'appendByteBuffer', + value: function appendByteBuffer(b, object) { + var field = null; + try { + var iterable = this.keys; + for (var i = 0, field; i < iterable.length; i++) { + field = iterable[i]; + var type = this.types[field]; + type.appendByteBuffer(b, object[field]); + } + } catch (error) { + try { + EC.throw(this.operation_name + '.' + field + " = " + JSON.stringify(object[field]), error); + } catch (e) { + // circular ref + EC.throw(this.operation_name + '.' + field + " = " + object[field], error); + } + } + return; + } + }, { + key: 'fromObject', + value: function fromObject(serialized_object) { + var result = {}; + var field = null; + try { + var iterable = this.keys; + for (var i = 0, field; i < iterable.length; i++) { + field = iterable[i]; + var type = this.types[field]; + var value = serialized_object[field]; + //DEBUG value = value.resolve if value.resolve + //DEBUG console.log('... value',field,value) + var object = type.fromObject(value); + result[field] = object; + } + } catch (error) { + EC.throw(this.operation_name + '.' + field, error); + } + + return result; + } + + /** + @arg {boolean} [debug.use_default = false] - more template friendly + @arg {boolean} [debug.annotate = false] - add user-friendly information + */ + + }, { + key: 'toObject', + value: function toObject() { + var serialized_object = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { use_default: false, annotate: false }; + + var result = {}; + var field = null; + try { + if (!this.types) return result; + + var iterable = this.keys; + for (var i = 0, field; i < iterable.length; i++) { + field = iterable[i]; + var type = this.types[field]; + var object = type.toObject(typeof serialized_object !== "undefined" && serialized_object !== null ? serialized_object[field] : undefined, debug); + result[field] = object; + if (HEX_DUMP) { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + type.appendByteBuffer(b, typeof serialized_object !== "undefined" && serialized_object !== null ? serialized_object[field] : undefined); + b = b.copy(0, b.offset); + console.error(this.operation_name + '.' + field, b.toHex()); + } + } + } catch (error) { + EC.throw(this.operation_name + '.' + field, error); + } + + return result; + } + + /** Sort by the first element in a operation */ + + }, { + key: 'compare', + value: function compare(a, b) { + + var first_key = this.keys[0]; + var first_type = this.types[first_key]; + + var valA = a[first_key]; + var valB = b[first_key]; + + if (first_type.compare) return first_type.compare(valA, valB); + + if (typeof valA === "number" && typeof valB === "number") return valA - valB; + + var encoding = void 0; + if (Buffer.isBuffer(valA) && Buffer.isBuffer(valB)) { + // A binary string compare does not work. If localeCompare is well supported that could replace HEX. Performanance is very good so comparing HEX works. + encoding = "hex"; + } + + var strA = valA.toString(encoding); + var strB = valB.toString(encoding); + return strA > strB ? 1 : strA < strB ? -1 : 0; + } + + // + + }, { + key: 'fromHex', + value: function fromHex(hex) { + var b = ByteBuffer.fromHex(hex, ByteBuffer.LITTLE_ENDIAN); + return this.fromByteBuffer(b); + } + }, { + key: 'fromBuffer', + value: function fromBuffer(buffer) { + var b = ByteBuffer.fromBinary(buffer.toString("binary"), ByteBuffer.LITTLE_ENDIAN); + return this.fromByteBuffer(b); + } + }, { + key: 'toHex', + value: function toHex(object) { + // return this.toBuffer(object).toString("hex") + var b = this.toByteBuffer(object); + return b.toHex(); + } + }, { + key: 'toByteBuffer', + value: function toByteBuffer(object) { + var b = new ByteBuffer(ByteBuffer.DEFAULT_CAPACITY, ByteBuffer.LITTLE_ENDIAN); + this.appendByteBuffer(b, object); + return b.copy(0, b.offset); + } + }, { + key: 'toBuffer', + value: function toBuffer(object) { + return new Buffer(this.toByteBuffer(object).toBinary(), 'binary'); + } + }]); + + return Serializer; +}(); + +module.exports = Serializer; \ No newline at end of file diff --git a/dist/serializer/src/template.js b/dist/serializer/src/template.js new file mode 100644 index 0000000..d1e5d0d --- /dev/null +++ b/dist/serializer/src/template.js @@ -0,0 +1,17 @@ +"use strict"; + +/** Console print any transaction object with zero default values. */ +module.exports = function template(op) { + + var object = op.toObject(void 0, { use_default: true, annotate: true }); + + // visual (with descriptions) + console.error(JSON.stringify(object, null, 4)); + + // usable in a copy-paste + + object = op.toObject(void 0, { use_default: true, annotate: false }); + + // copy-paste one-lineer + console.error(JSON.stringify(object)); +}; \ No newline at end of file diff --git a/dist/serializer/src/types.js b/dist/serializer/src/types.js new file mode 100644 index 0000000..45a0225 --- /dev/null +++ b/dist/serializer/src/types.js @@ -0,0 +1,1024 @@ +'use strict'; + +var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); + +var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; + +// Low-level types that make up operations + +var v = require('./SerializerValidation'); +var fp = require('./FastParser'); + +var ChainTypes = require("../../chain/src/ChainTypes"); +var ObjectId = require("../../chain/src/ObjectId"); + +var _require = require("../../ecc"), + PublicKey = _require.PublicKey, + Address = _require.Address; + +var _require2 = require("peerplaysjs-ws"), + ChainConfig = _require2.ChainConfig; + +var Types = {}; +module.exports = Types; + +var HEX_DUMP = process.env.npm_config__graphene_serializer_hex_dump; + +Types.uint8 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint8(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.require_range(0, 0xFF, object, 'uint8 ' + object); + b.writeUint8(object); + return; + }, + fromObject: function fromObject(object) { + v.require_range(0, 0xFF, object, 'uint8 ' + object); + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return 0; + } + v.require_range(0, 0xFF, object, 'uint8 ' + object); + return parseInt(object); + } +}; + +Types.uint16 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint16(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.require_range(0, 0xFFFF, object, 'uint16 ' + object); + b.writeUint16(object); + return; + }, + fromObject: function fromObject(object) { + v.require_range(0, 0xFFFF, object, 'uint16 ' + object); + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return 0; + } + v.require_range(0, 0xFFFF, object, 'uint16 ' + object); + return parseInt(object); + } +}; + +Types.uint32 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint32(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.require_range(0, 0xFFFFFFFF, object, 'uint32 ' + object); + b.writeUint32(object); + return; + }, + fromObject: function fromObject(object) { + v.require_range(0, 0xFFFFFFFF, object, 'uint32 ' + object); + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return 0; + } + v.require_range(0, 0xFFFFFFFF, object, 'uint32 ' + object); + return parseInt(object); + } +}; + +var MIN_SIGNED_32 = -1 * Math.pow(2, 31); +var MAX_SIGNED_32 = Math.pow(2, 31) - 1; + +Types.varint32 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readVarint32(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.require_range(MIN_SIGNED_32, MAX_SIGNED_32, object, 'uint32 ' + object); + b.writeVarint32(object); + return; + }, + fromObject: function fromObject(object) { + v.require_range(MIN_SIGNED_32, MAX_SIGNED_32, object, 'uint32 ' + object); + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return 0; + } + v.require_range(MIN_SIGNED_32, MAX_SIGNED_32, object, 'uint32 ' + object); + return parseInt(object); + } +}; + +Types.int64 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readInt64(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + b.writeInt64(v.to_long(object)); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + return v.to_long(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return "0"; + } + v.required(object); + return v.to_long(object).toString(); + } +}; + +Types.uint64 = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint64(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + b.writeUint64(v.to_ulong(v.unsigned(object))); + return; + }, + fromObject: function fromObject(object) { + return v.to_ulong(v.unsigned(object)); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return "0"; + } + return v.to_ulong(object).toString(); + } +}; + +Types.string = { + fromByteBuffer: function fromByteBuffer(b) { + var b_copy; + var len = b.readVarint32(); + b_copy = b.copy(b.offset, b.offset + len), b.skip(len); + return new Buffer(b_copy.toBinary(), 'binary'); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + b.writeVarint32(object.length); + b.append(object.toString('binary'), 'binary'); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + return new Buffer(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return ""; + } + return object.toString(); + } +}; + +Types.bytes = function (size) { + return { + fromByteBuffer: function fromByteBuffer(b) { + if (size === undefined) { + var b_copy; + var len = b.readVarint32(); + b_copy = b.copy(b.offset, b.offset + len), b.skip(len); + return new Buffer(b_copy.toBinary(), 'binary'); + } else { + b_copy = b.copy(b.offset, b.offset + size), b.skip(size); + return new Buffer(b_copy.toBinary(), 'binary'); + } + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + if (typeof object === "string") object = new Buffer(object, "hex"); + + if (size === undefined) { + b.writeVarint32(object.length); + } + b.append(object.toString('binary'), 'binary'); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + if (Buffer.isBuffer(object)) return object; + + return new Buffer(object, 'hex'); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + var zeros = function zeros(num) { + return new Array(num).join("00"); + }; + return zeros(size); + } + v.required(object); + return object.toString('hex'); + } + }; +}; + +Types.bool = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint8() === 1; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + // supports boolean or integer + b.writeUint8(JSON.parse(object) ? 1 : 0); + return; + }, + fromObject: function fromObject(object) { + return JSON.parse(object) ? true : false; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return false; + } + return JSON.parse(object) ? true : false; + } +}; + +Types.void = { + fromByteBuffer: function fromByteBuffer(b) { + throw new Error("(void) undefined type"); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + throw new Error("(void) undefined type"); + }, + fromObject: function fromObject(object) { + throw new Error("(void) undefined type"); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return undefined; + } + throw new Error("(void) undefined type"); + } +}; + +Types.array = function (st_operation) { + return { + fromByteBuffer: function fromByteBuffer(b) { + var size = b.readVarint32(); + if (HEX_DUMP) { + console.log("varint32 size = " + size.toString(16)); + } + var result = []; + for (var i = 0; 0 < size ? i < size : i > size; 0 < size ? i++ : i++) { + result.push(st_operation.fromByteBuffer(b)); + } + return sortOperation(result, st_operation); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + object = sortOperation(object, st_operation); + b.writeVarint32(object.length); + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + st_operation.appendByteBuffer(b, o); + } + }, + fromObject: function fromObject(object) { + v.required(object); + object = sortOperation(object, st_operation); + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push(st_operation.fromObject(o)); + } + return result; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return [st_operation.toObject(object, debug)]; + } + v.required(object); + object = sortOperation(object, st_operation); + + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push(st_operation.toObject(o, debug)); + } + return result; + } + }; +}; + +Types.time_point_sec = { + fromByteBuffer: function fromByteBuffer(b) { + return b.readUint32(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + if (typeof object !== "number") object = Types.time_point_sec.fromObject(object); + + b.writeUint32(object); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + + if (typeof object === "number") return object; + + if (object.getTime) return Math.floor(object.getTime() / 1000); + + if (typeof object !== "string") throw new Error("Unknown date type: " + object); + + // if(typeof object === "string" && !/Z$/.test(object)) + // object = object + "Z" + + return Math.floor(new Date(object).getTime() / 1000); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) return new Date(0).toISOString().split('.')[0]; + + v.required(object); + + if (typeof object === "string") return object; + + if (object.getTime) return object.toISOString().split('.')[0]; + + var int = parseInt(object); + v.require_range(0, 0xFFFFFFFF, int, 'uint32 ' + object); + return new Date(int * 1000).toISOString().split('.')[0]; + } +}; + +Types.set = function (st_operation) { + return { + validate: function validate(array) { + var dup_map = {}; + for (var i = 0, o; i < array.length; i++) { + o = array[i]; + var ref; + if (ref = typeof o === 'undefined' ? 'undefined' : _typeof(o), ['string', 'number'].indexOf(ref) >= 0) { + if (dup_map[o] !== undefined) { + throw new Error("duplicate (set)"); + } + dup_map[o] = true; + } + } + return sortOperation(array, st_operation); + }, + fromByteBuffer: function fromByteBuffer(b) { + var size = b.readVarint32(); + if (HEX_DUMP) { + console.log("varint32 size = " + size.toString(16)); + } + return this.validate(function () { + var result = []; + for (var i = 0; 0 < size ? i < size : i > size; 0 < size ? i++ : i++) { + result.push(st_operation.fromByteBuffer(b)); + } + return result; + }()); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + if (!object) { + object = []; + } + b.writeVarint32(object.length); + var iterable = this.validate(object); + for (var i = 0, o; i < iterable.length; i++) { + o = iterable[i]; + st_operation.appendByteBuffer(b, o); + } + return; + }, + fromObject: function fromObject(object) { + if (!object) { + object = []; + } + return this.validate(function () { + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push(st_operation.fromObject(o)); + } + return result; + }()); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return [st_operation.toObject(object, debug)]; + } + if (!object) { + object = []; + } + return this.validate(function () { + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push(st_operation.toObject(o, debug)); + } + return result; + }()); + } + }; +}; + +// global_parameters_update_operation current_fees +Types.fixed_array = function (count, st_operation) { + return { + fromByteBuffer: function fromByteBuffer(b) { + var i, j, ref, results; + results = []; + for (i = j = 0, ref = count; j < ref; i = j += 1) { + results.push(st_operation.fromByteBuffer(b)); + } + return sortOperation(results, st_operation); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + var i, j, ref; + if (count !== 0) { + v.required(object); + object = sortOperation(object, st_operation); + } + for (i = j = 0, ref = count; j < ref; i = j += 1) { + st_operation.appendByteBuffer(b, object[i]); + } + }, + fromObject: function fromObject(object) { + var i, j, ref, results; + if (count !== 0) { + v.required(object); + } + results = []; + for (i = j = 0, ref = count; j < ref; i = j += 1) { + results.push(st_operation.fromObject(object[i])); + } + return results; + }, + toObject: function toObject(object, debug) { + var i, j, k, ref, ref1, results, results1; + if (debug == null) { + debug = {}; + } + if (debug.use_default && object === void 0) { + results = []; + for (i = j = 0, ref = count; j < ref; i = j += 1) { + results.push(st_operation.toObject(void 0, debug)); + } + return results; + } + if (count !== 0) { + v.required(object); + } + results1 = []; + for (i = k = 0, ref1 = count; k < ref1; i = k += 1) { + results1.push(st_operation.toObject(object[i], debug)); + } + return results1; + } + }; +}; + +/* Supports instance numbers (11) or object types (1.2.11). Object type +Validation is enforced when an object type is used. */ +var id_type = function id_type(reserved_spaces, object_type) { + v.required(reserved_spaces, "reserved_spaces"); + v.required(object_type, "object_type"); + return { + fromByteBuffer: function fromByteBuffer(b) { + return b.readVarint32(); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + // convert 1.2.n into just n + if (/^[0-9]+\.[0-9]+\.[0-9]+$/.test(object)) { + object = v.get_instance(reserved_spaces, object_type, object); + } + b.writeVarint32(v.to_number(object)); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + if (v.is_digits(object)) { + return v.to_number(object); + } + return v.get_instance(reserved_spaces, object_type, object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var object_type_id = ChainTypes.object_type[object_type]; + if (debug.use_default && object === undefined) { + return reserved_spaces + '.' + object_type_id + '.0'; + } + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + if (/^[0-9]+\.[0-9]+\.[0-9]+$/.test(object)) { + object = v.get_instance(reserved_spaces, object_type, object); + } + + return reserved_spaces + '.' + object_type_id + '.' + object; + } + }; +}; + +Types.protocol_id_type = function (name) { + v.required(name, "name"); + return id_type(ChainTypes.reserved_spaces.protocol_ids, name); +}; + +Types.object_id_type = { + fromByteBuffer: function fromByteBuffer(b) { + return ObjectId.fromByteBuffer(b); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + object = ObjectId.fromString(object); + object.appendByteBuffer(b); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + return ObjectId.fromString(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return "0.0.0"; + } + v.required(object); + if (object.resolve !== undefined) { + object = object.resolve; + } + object = ObjectId.fromString(object); + return object.toString(); + } +}; + +Types.vote_id = { TYPE: 0x000000FF, + ID: 0xFFFFFF00, + fromByteBuffer: function fromByteBuffer(b) { + var value = b.readUint32(); + return { + type: value & this.TYPE, + id: value & this.ID + }; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + if (object === "string") object = Types.vote_id.fromObject(object); + + var value = object.id << 8 | object.type; + b.writeUint32(value); + return; + }, + fromObject: function fromObject(object) { + v.required(object, "(type vote_id)"); + if ((typeof object === 'undefined' ? 'undefined' : _typeof(object)) === "object") { + v.required(object.type, "type"); + v.required(object.id, "id"); + return object; + } + v.require_test(/^[0-9]+:[0-9]+$/, object, 'vote_id format ' + object); + + var _object$split = object.split(':'), + _object$split2 = _slicedToArray(_object$split, 2), + type = _object$split2[0], + id = _object$split2[1]; + + v.require_range(0, 0xff, type, 'vote type ' + object); + v.require_range(0, 0xffffff, id, 'vote id ' + object); + return { type: type, id: id }; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return "0:0"; + } + v.required(object); + if (typeof object === "string") object = Types.vote_id.fromObject(object); + + return object.type + ":" + object.id; + }, + compare: function compare(a, b) { + if ((typeof a === 'undefined' ? 'undefined' : _typeof(a)) !== "object") a = Types.vote_id.fromObject(a); + if ((typeof b === 'undefined' ? 'undefined' : _typeof(b)) !== "object") b = Types.vote_id.fromObject(b); + return parseInt(a.id) - parseInt(b.id); + } +}; + +Types.optional = function (st_operation) { + v.required(st_operation, "st_operation"); + return { + fromByteBuffer: function fromByteBuffer(b) { + if (!(b.readUint8() === 1)) { + return undefined; + } + return st_operation.fromByteBuffer(b); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + if (object !== null && object !== undefined) { + b.writeUint8(1); + st_operation.appendByteBuffer(b, object); + } else { + b.writeUint8(0); + } + return; + }, + fromObject: function fromObject(object) { + if (object === undefined) { + return undefined; + } + return st_operation.fromObject(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + // toObject is only null save if use_default is true + var result_object = function () { + if (!debug.use_default && object === undefined) { + return undefined; + } else { + return st_operation.toObject(object, debug); + } + }(); + + if (debug.annotate) { + if ((typeof result_object === 'undefined' ? 'undefined' : _typeof(result_object)) === "object") { + result_object.__optional = "parent is optional"; + } else { + result_object = { __optional: result_object }; + } + } + return result_object; + } + }; +}; + +Types.static_variant = function (_st_operations) { + return { + nosort: true, + st_operations: _st_operations, + fromByteBuffer: function fromByteBuffer(b) { + var type_id = b.readVarint32(); + var st_operation = this.st_operations[type_id]; + if (HEX_DUMP) { + console.error('static_variant id 0x' + type_id.toString(16) + ' (' + type_id + ')'); + } + v.required(st_operation, 'operation ' + type_id); + return [type_id, st_operation.fromByteBuffer(b)]; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + var type_id = object[0]; + var st_operation = this.st_operations[type_id]; + v.required(st_operation, 'operation ' + type_id); + b.writeVarint32(type_id); + st_operation.appendByteBuffer(b, object[1]); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + var type_id = object[0]; + var st_operation = this.st_operations[type_id]; + v.required(st_operation, 'operation ' + type_id); + return [type_id, st_operation.fromObject(object[1])]; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return [0, this.st_operations[0].toObject(undefined, debug)]; + } + v.required(object); + var type_id = object[0]; + var st_operation = this.st_operations[type_id]; + v.required(st_operation, 'operation ' + type_id); + return [type_id, st_operation.toObject(object[1], debug)]; + } + }; +}; + +Types.map = function (key_st_operation, value_st_operation) { + return { + validate: function validate(array) { + if (!Array.isArray(array)) { + throw new Error("expecting array"); + } + var dup_map = {}; + for (var i = 0, o; i < array.length; i++) { + o = array[i]; + var ref; + if (!(o.length === 2)) { + throw new Error("expecting two elements"); + } + if (ref = _typeof(o[0]), ['number', 'string'].indexOf(ref) >= 0) { + if (dup_map[o[0]] !== undefined) { + throw new Error("duplicate (map)"); + } + dup_map[o[0]] = true; + } + } + return sortOperation(array, key_st_operation); + }, + fromByteBuffer: function fromByteBuffer(b) { + var result = []; + var end = b.readVarint32(); + for (var i = 0; 0 < end ? i < end : i > end; 0 < end ? i++ : i++) { + result.push([key_st_operation.fromByteBuffer(b), value_st_operation.fromByteBuffer(b)]); + } + return this.validate(result); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + this.validate(object); + b.writeVarint32(object.length); + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + key_st_operation.appendByteBuffer(b, o[0]); + value_st_operation.appendByteBuffer(b, o[1]); + } + return; + }, + fromObject: function fromObject(object) { + v.required(object); + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push([key_st_operation.fromObject(o[0]), value_st_operation.fromObject(o[1])]); + } + return this.validate(result); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return [[key_st_operation.toObject(undefined, debug), value_st_operation.toObject(undefined, debug)]]; + } + v.required(object); + object = this.validate(object); + var result = []; + for (var i = 0, o; i < object.length; i++) { + o = object[i]; + result.push([key_st_operation.toObject(o[0], debug), value_st_operation.toObject(o[1], debug)]); + } + return result; + } + }; +}; + +Types.public_key = { + toPublic: function toPublic(object) { + if (object.resolve !== undefined) { + object = object.resolve; + } + + if (object instanceof PublicKey) { + return object; + } + + return object == null ? object : object.Q ? object : PublicKey.fromStringOrThrow(object); + }, + fromByteBuffer: function fromByteBuffer(b) { + return fp.public_key(b); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + v.required(object); + fp.public_key(b, Types.public_key.toPublic(object)); + return; + }, + fromObject: function fromObject(object) { + v.required(object); + if (object.Q) { + return object; + } + return Types.public_key.toPublic(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return ChainConfig.address_prefix + "859gxfnXyUriMgUeThh1fWv3oqcpLFyHa3TfFYC4PK2HqhToVM"; + } + v.required(object); + return object.toString(); + }, + compare: function compare(a, b) { + return strCmp(a.toAddressString(), b.toAddressString()); + } +}; + +Types.address = { + _to_address: function _to_address(object) { + v.required(object); + if (object.addy) { + return object; + } + return Address.fromString(object); + }, + fromByteBuffer: function fromByteBuffer(b) { + return new Address(fp.ripemd160(b)); + }, + appendByteBuffer: function appendByteBuffer(b, object) { + fp.ripemd160(b, Types.address._to_address(object).toBuffer()); + return; + }, + fromObject: function fromObject(object) { + return Types.address._to_address(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return ChainConfig.address_prefix + "664KmHxSuQyDsfwo4WEJvWpzg1QKdg67S"; + } + return Types.address._to_address(object).toString(); + }, + compare: function compare(a, b) { + return strCmp(a.toString(), b.toString()); + } +}; + +Types.variant = { + fromByteBuffer: function fromByteBuffer(b) { + var type = b.readUint8(); + switch (type) { + case 0: + return null; + case 1: + return Types.int64.fromByteBuffer(b); + case 2: + return Types.uint64.fromByteBuffer(b); + case 3: + return b.readDouble(); + case 4: + return Types.bool.fromByteBuffer(b); + case 5: + return Types.string.fromByteBuffer(b); + case 6: + return Types.array(Types.variant).fromByteBuffer(b); + case 7: + default: + return Types.variant_object.fromByteBuffer(b); + }; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + if (typeof object == 'number') { + if (Number.isInteger(object)) { + if (object >= 0) { + b.writeUint8(2); + Types.uint64.appendByteBuffer(b, object); + } else { + b.writeUint8(1); + Types.int64.appendByteBuffer(b, object); + } + } else { + b.writeUint8(3); + b.writeDouble(Number.parseFloat(object)); + } + } else if (typeof object == 'boolean') { + b.writeUint8(4); + Types.bool.appendByteBuffer(b, object); + } else if (typeof object == 'string') { + b.writeUint8(5); + Types.string.appendByteBuffer(b, object); + } else if (typeof object == 'array') { + b.writeUint8(6); + Types.array(Types.variant).appendByteBuffer(b, object); + } else { + b.writeUint8(7); + Types.variant_object.appendByteBuffer(b, object); + } + }, + fromObject: function fromObject(object) { + return JSON.parse(object); + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + return null; + } + return JSON.parse(object); + } +}; + +Types.variant_object = { + fromByteBuffer: function fromByteBuffer(b) { + var count = b.readVarint32(); + var result = {}; + for (var i = 0; i < count; ++i) { + var key = Types.string.fromByteBuffer(b); + result[key] = Types.variant.fromByteBuffer(b); + } + return result; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + var count = 0; + for (var key in object) { + if (object.hasOwnProperty(key)) ++count; + }b.writeVarint32(count); // number of key/value pairs + for (var key in object) { + if (object.hasOwnProperty(key)) { + Types.string.appendByteBuffer(b, key); + Types.variant.appendByteBuffer(b, object[key]); + } + }return; + }, + fromObject: function fromObject(object) { + var newObject = {}; + for (var key in object) { + if (object.hasOwnProperty(key)) newObject[key] = object[key]; + }return newObject; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + var newObject = {}; + for (var key in object) { + if (object.hasOwnProperty(key)) newObject[key] = object[key]; + }return newObject; + } +}; + +Types.enumeration = function (values) { + return { + fromByteBuffer: function fromByteBuffer(b) { + return values[b.readVarint32ZigZag()]; + }, + appendByteBuffer: function appendByteBuffer(b, object) { + b.writeVarint32ZigZag(values.indexOf(object)); + return; + }, + fromObject: function fromObject(object) { + return object; + }, + toObject: function toObject(object) { + var debug = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + + if (debug.use_default && object === undefined) { + values[0]; + } + return object; + } + }; +}; + +Types.sha256 = Types.bytes(32); + +var strCmp = function strCmp(a, b) { + return a > b ? 1 : a < b ? -1 : 0; +}; +var firstEl = function firstEl(el) { + return Array.isArray(el) ? el[0] : el; +}; +var sortOperation = function sortOperation(array, st_operation) { + return st_operation.nosort ? array : st_operation.compare ? array.sort(function (a, b) { + return st_operation.compare(firstEl(a), firstEl(b)); + }) : // custom compare operation + array.sort(function (a, b) { + return typeof firstEl(a) === "number" && typeof firstEl(b) === "number" ? firstEl(a) - firstEl(b) : + // A binary string compare does not work. Performanance is very good so HEX is used.. localeCompare is another option. + Buffer.isBuffer(firstEl(a)) && Buffer.isBuffer(firstEl(b)) ? strCmp(firstEl(a).toString("hex"), firstEl(b).toString("hex")) : strCmp(firstEl(a).toString(), firstEl(b).toString()); + }); +}; \ No newline at end of file diff --git a/lib/chain/src/ChainStore.js b/lib/chain/src/ChainStore.js index 9dc0d16..7a21360 100644 --- a/lib/chain/src/ChainStore.js +++ b/lib/chain/src/ChainStore.js @@ -75,7 +75,8 @@ class ChainStore { this.balance_objects_by_address = Immutable.Map(); this.get_account_refs_of_keys_calls = Immutable.Set(); this.account_history_requests = new Map(); ///< tracks pending history requests - this.witness_by_account_id = new Map(); + this.witness_by_account_id = new Map(); + this.witnesses = Immutable.Set(); this.account_by_witness_id = new Map(); this.committee_by_account_id = new Map(); this.objects_by_vote_id = new Map(); @@ -735,7 +736,32 @@ class ChainStore { } return null } - + + /** + * + * @returns a promise with a list of all witness ids. Regardless of if they have been voted in or not. + * @memberof ChainStore + */ + fetchWitnessAccounts() { + return new Promise((resolve, reject) => { + Apis.instance().db_api().exec("lookup_witness_accounts", [0, 1000]).then((w) => { + if (w) { + let witnessArr = []; + + for (let i = 0, length = w.length; i < length; i++) { + witnessArr.push(w[i][1]); // ids only + } + + this.witnesses = this.witnesses.merge(witnessArr); + this._updateObject(witnessArr, true); + resolve(this.witnesses); + } else { + resolve(null); + } + }); + }); + } + /** * * @return a promise with the witness object diff --git a/package-lock.json b/package-lock.json index b301f25..ef7f982 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,15 @@ { "name": "peerplaysjs-lib", - "version": "0.4.19", + "version": "0.4.20", "lockfileVersion": 1, "requires": true, "dependencies": { + "@types/node": { + "version": "10.5.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.5.2.tgz", + "integrity": "sha512-m9zXmifkZsMHZBOyxZWilMwmTlpC8x5Ty360JKTiXvlXZfBWYpsg9ZZvP/Ye+iZUh+Q+MxDLjItVTWIsfwz+8Q==", + "dev": true + }, "JSONStream": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz", @@ -79,13 +85,6 @@ "json-schema-traverse": "^0.3.0" } }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true, - "optional": true - }, "ansi-regex": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", @@ -877,7 +876,7 @@ }, "base-x": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/base-x/-/base-x-1.1.0.tgz", "integrity": "sha1-QtPXF0dPnqAiB/bRqh9CaRPut6w=" }, "base64-js": { @@ -909,9 +908,9 @@ "optional": true }, "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", + "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" }, "bn.js": { "version": "4.11.8", @@ -1039,6 +1038,17 @@ "xtend": "^4.0.0" }, "dependencies": { + "buffer": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", + "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, "string_decoder": { "version": "0.10.31", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", @@ -1126,17 +1136,6 @@ "base-x": "^1.1.0" } }, - "buffer": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", - "integrity": "sha1-bRu2AbB6TvztlwlBMgkwJ8lbwpg=", - "dev": true, - "requires": { - "base64-js": "^1.0.2", - "ieee754": "^1.1.4", - "isarray": "^1.0.0" - } - }, "buffer-from": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", @@ -1190,17 +1189,17 @@ } }, "cheerio": { - "version": "0.20.0", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", - "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", + "version": "1.0.0-rc.2", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.2.tgz", + "integrity": "sha1-S59TqBsn5NXawxwP/Qz6A8xoMNs=", "dev": true, "requires": { "css-select": "~1.2.0", "dom-serializer": "~0.1.0", "entities": "~1.1.1", - "htmlparser2": "~3.8.1", - "jsdom": "^7.0.2", - "lodash": "^4.1.0" + "htmlparser2": "^3.9.1", + "lodash": "^4.15.0", + "parse5": "^3.0.1" } }, "chokidar": { @@ -1238,9 +1237,9 @@ "optional": true }, "color-logger": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.3.tgz", - "integrity": "sha1-2bIt0dlz4Waxi/MT+fSBu6TfIBg=", + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.6.tgz", + "integrity": "sha1-5WJF7ymCJlcRDHy3WpzXhstp7Rs=", "dev": true }, "combine-source-map": { @@ -1368,7 +1367,7 @@ }, "create-hash": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", "requires": { "cipher-base": "^1.0.1", @@ -1380,7 +1379,7 @@ }, "create-hmac": { "version": "1.1.7", - "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "resolved": "http://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", "requires": { "cipher-base": "^1.0.3", @@ -1451,7 +1450,7 @@ }, "d": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "requires": { "es5-ext": "^0.10.9" @@ -1491,7 +1490,8 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", - "dev": true + "dev": true, + "optional": true }, "defined": { "version": "1.0.0", @@ -1594,9 +1594,9 @@ "dev": true }, "domhandler": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", - "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz", + "integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==", "dev": true, "requires": { "domelementtype": "1" @@ -1691,9 +1691,9 @@ } }, "escape-html": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.2.tgz", - "integrity": "sha1-130y+pjjjC9BroXpJ44ODmuhAiw=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", "dev": true }, "escape-string-regexp": { @@ -1703,87 +1703,68 @@ "dev": true }, "escodegen": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.7.0.tgz", - "integrity": "sha1-TimdjMMwh7fynBniuehDYqvjVFM=", + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.10.0.tgz", + "integrity": "sha512-fjUOf8johsv23WuIKdNQU4P9t9jhQ4Qzx6pC2uW890OloK3Zs1ZAoCNpg/2larNF501jLl3UNy0kIRcF6VI22g==", "dev": true, + "optional": true, "requires": { - "esprima": "^1.2.2", - "estraverse": "^1.9.1", + "esprima": "^3.1.3", + "estraverse": "^4.2.0", "esutils": "^2.0.2", - "optionator": "^0.5.0", - "source-map": "~0.2.0" + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "dependencies": { - "esprima": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.5.tgz", - "integrity": "sha1-CZNQL+r2aBODJXVvMPmlH+7sEek=", - "dev": true - }, - "estraverse": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", - "integrity": "sha1-r2fy3JIlgkFZUJJgkaQAXSnJu0Q=", - "dev": true - }, "source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha1-2rc/vPwrqBm03gO9b26qSBZLP50=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, - "optional": true, - "requires": { - "amdefine": ">=0.0.4" - } + "optional": true } } }, "esdoc": { - "version": "0.4.8", - "resolved": "https://registry.npmjs.org/esdoc/-/esdoc-0.4.8.tgz", - "integrity": "sha1-SXLitt6F4rkpozDtVLjF8/3OvTM=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/esdoc/-/esdoc-1.1.0.tgz", + "integrity": "sha512-vsUcp52XJkOWg9m1vDYplGZN2iDzvmjDL5M/Mp8qkoDG3p2s0yIQCIjKR5wfPBaM3eV14a6zhQNYiNTCVzPnxA==", "dev": true, "requires": { - "cheerio": "0.20.0", - "color-logger": "0.0.3", - "core-js": "0.9.18", - "escape-html": "1.0.2", - "escodegen": "1.7.0", - "espree": "2.2.0", - "estraverse": "4.1.0", - "fs-extra": "0.26.5", + "babel-generator": "6.26.1", + "babel-traverse": "6.26.0", + "babylon": "6.18.0", + "cheerio": "1.0.0-rc.2", + "color-logger": "0.0.6", + "escape-html": "1.0.3", + "fs-extra": "5.0.0", "ice-cap": "0.0.4", - "marked": "0.3.5", - "minimist": "1.1.1", - "taffydb": "2.7.2" + "marked": "0.3.19", + "minimist": "1.2.0", + "taffydb": "2.7.3" }, "dependencies": { - "core-js": { - "version": "0.9.18", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-0.9.18.tgz", - "integrity": "sha1-E/RY5DAjKw9OwfSA2nwvUojp0JU=", - "dev": true - }, "minimist": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.1.1.tgz", - "integrity": "sha1-G8K8cWWM3KVxJHVoQ2NhWwtPaVs=", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } } }, - "espree": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-2.2.0.tgz", - "integrity": "sha1-AdySen6lCB0ae21hAknmJOf+89Y=", - "dev": true + "esprima": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-3.1.3.tgz", + "integrity": "sha1-/cpRzuYTOJXjyI1TXOSdv/YqRjM=", + "dev": true, + "optional": true }, "estraverse": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.1.0.tgz", - "integrity": "sha1-QPI6dgkgQb5kZ9fyNckztnB2bgU=", - "dev": true + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true, + "optional": true }, "esutils": { "version": "2.0.2", @@ -1874,10 +1855,11 @@ "optional": true }, "fast-levenshtein": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-1.0.7.tgz", - "integrity": "sha1-AXjc3uAjuSkFGTrwlZ6KdjnP3Lk=", - "dev": true + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true, + "optional": true }, "filename-regex": { "version": "2.0.1", @@ -1937,16 +1919,14 @@ } }, "fs-extra": { - "version": "0.26.5", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.26.5.tgz", - "integrity": "sha1-U6x0Znygg/0twXEsgTA5yjLWmn8=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", "dev": true, "requires": { "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0", - "path-is-absolute": "^1.0.0", - "rimraf": "^2.2.8" + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, "fs-readdir-recursive": { @@ -2647,48 +2627,17 @@ "dev": true }, "htmlparser2": { - "version": "3.8.3", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", - "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.9.2.tgz", + "integrity": "sha1-G9+HrMoPP55T+k/M6w9LTLsAszg=", "dev": true, "requires": { - "domelementtype": "1", - "domhandler": "2.3", - "domutils": "1.5", - "entities": "1.0", - "readable-stream": "1.1" - }, - "dependencies": { - "entities": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", - "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", - "dev": true - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } + "domelementtype": "^1.3.0", + "domhandler": "^2.3.0", + "domutils": "^1.5.1", + "entities": "^1.1.1", + "inherits": "^2.0.1", + "readable-stream": "^2.0.2" } }, "http-signature": { @@ -2717,6 +2666,82 @@ "requires": { "cheerio": "0.20.0", "color-logger": "0.0.3" + }, + "dependencies": { + "cheerio": { + "version": "0.20.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.20.0.tgz", + "integrity": "sha1-XHEPK6uVZTJyhCugHG6mGzVF7DU=", + "dev": true, + "requires": { + "css-select": "~1.2.0", + "dom-serializer": "~0.1.0", + "entities": "~1.1.1", + "htmlparser2": "~3.8.1", + "jsdom": "^7.0.2", + "lodash": "^4.1.0" + } + }, + "color-logger": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/color-logger/-/color-logger-0.0.3.tgz", + "integrity": "sha1-2bIt0dlz4Waxi/MT+fSBu6TfIBg=", + "dev": true + }, + "domhandler": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.3.0.tgz", + "integrity": "sha1-LeWaCCLVAn+r/28DLCsloqir5zg=", + "dev": true, + "requires": { + "domelementtype": "1" + } + }, + "htmlparser2": { + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.8.3.tgz", + "integrity": "sha1-mWwosZFRaovoZQGn15dX5ccMEGg=", + "dev": true, + "requires": { + "domelementtype": "1", + "domhandler": "2.3", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + }, + "dependencies": { + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=", + "dev": true + } + } + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } } }, "ieee754": { @@ -2986,6 +3011,13 @@ "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=", "dev": true, "optional": true + }, + "parse5": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", + "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "dev": true, + "optional": true } } }, @@ -3032,9 +3064,9 @@ "dev": true }, "jsonfile": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", - "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { "graceful-fs": "^4.1.6" @@ -3074,15 +3106,6 @@ "is-buffer": "^1.1.5" } }, - "klaw": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", - "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.9" - } - }, "labeled-stream-splicer": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/labeled-stream-splicer/-/labeled-stream-splicer-2.0.1.tgz", @@ -3103,13 +3126,14 @@ } }, "levn": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.2.5.tgz", - "integrity": "sha1-uo0znQykphDjo/FFucr0iAcVUFQ=", + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, + "optional": true, "requires": { - "prelude-ls": "~1.1.0", - "type-check": "~0.3.1" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "lodash": { @@ -3150,16 +3174,10 @@ "js-tokens": "^3.0.0 || ^4.0.0" } }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true - }, "marked": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.5.tgz", - "integrity": "sha1-QROhWsXXvKFYpargciRYe5+hW5Q=", + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/marked/-/marked-0.3.19.tgz", + "integrity": "sha512-ea2eGWOqNxPcXv8dyERdSr/6FmzvWwzjMxpfGB/sbMccXoct+xY+YukPD+QTUZwyvK7BZwcr4m21WBOW41pAkg==", "dev": true }, "math-random": { @@ -3310,6 +3328,12 @@ "minimatch": "0.3" } }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, "minimatch": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.3.0.tgz", @@ -3372,7 +3396,7 @@ }, "next-tick": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "normalize-path": { @@ -3440,24 +3464,20 @@ } }, "optionator": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.5.0.tgz", - "integrity": "sha1-t1qJlaLUF98ltuTjhi9QqohlE2g=", + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, + "optional": true, "requires": { - "deep-is": "~0.1.2", - "fast-levenshtein": "~1.0.0", - "levn": "~0.2.5", - "prelude-ls": "~1.1.1", - "type-check": "~0.3.1", - "wordwrap": "~0.0.2" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" } }, - "options": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/options/-/options-0.0.6.tgz", - "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=" - }, "os-browserify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.1.2.tgz", @@ -3529,11 +3549,13 @@ } }, "parse5": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-1.5.1.tgz", - "integrity": "sha1-m387DeMr543CQBsXVzzK8Pb1nZQ=", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", "dev": true, - "optional": true + "requires": { + "@types/node": "*" + } }, "path-browserify": { "version": "0.0.1", @@ -3574,16 +3596,9 @@ }, "peerplaysjs-ws": { "version": "0.1.11", - "resolved": "https://registry.npmjs.org/peerplaysjs-ws/-/peerplaysjs-ws-0.1.11.tgz", - "integrity": "sha1-6q6x5yXurfWcpgJ8Zx8yDXAlG+8=", + "resolved": "git+ssh://git@github.com/PBSA/peerplaysjs-ws.git#a92c3d94297d79e41c75c0c9f63898e59a888a2a", "requires": { - "ws": "^1.1.4" - }, - "dependencies": { - "ReconnectingWebSocket": { - "version": "git+https://github.com/svk31/reconnecting-websocket.git#464ed2e54eb37b90b7f4f8532427ac2753d87148", - "from": "git+https://github.com/svk31/reconnecting-websocket.git#464ed2e54eb37b90b7f4f8532427ac2753d87148" - } + "ws": "2.3.1" } }, "performance-now": { @@ -3898,15 +3913,6 @@ "path-parse": "^1.0.5" } }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, "ripemd160": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", @@ -3949,7 +3955,7 @@ }, "sha.js": { "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "resolved": "http://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", "requires": { "inherits": "^2.0.1", @@ -4130,9 +4136,9 @@ } }, "taffydb": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.2.tgz", - "integrity": "sha1-e/gQalwaSCUbPjvAoOFzJIn9Dcg=", + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/taffydb/-/taffydb-2.7.3.tgz", + "integrity": "sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ=", "dev": true }, "through": { @@ -4247,9 +4253,9 @@ "dev": true }, "ultron": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.0.2.tgz", - "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==" }, "umd": { "version": "3.0.3", @@ -4269,6 +4275,12 @@ "xtend": "^4.0.1" } }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, "url": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", @@ -4371,10 +4383,11 @@ } }, "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true, + "optional": true }, "wrappy": { "version": "1.0.2", @@ -4383,12 +4396,19 @@ "dev": true }, "ws": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ws/-/ws-1.1.5.tgz", - "integrity": "sha512-o3KqipXNUdS7wpQzBHSe180lBGO60SoK0yVo3CYJgb2MkobuWuBX6dhkYP5ORCLd55y+SaflMOV5fqAB53ux4w==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-2.3.1.tgz", + "integrity": "sha1-a5Sz5EfLajY/eF6vlK9jWejoHIA=", "requires": { - "options": ">=0.0.5", - "ultron": "1.0.x" + "safe-buffer": "~5.0.1", + "ultron": "~1.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.0.1.tgz", + "integrity": "sha1-0mPKVGls2KMGtcplUekt5XkY++c=" + } } }, "xml-name-validator": { diff --git a/package.json b/package.json index 689ed0c..9b521be 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "peerplaysjs-lib", - "version": "0.4.19", + "version": "0.4.20", "description": "Pure JavaScript Peerplays/Graphene library for node.js and browsers.", "browser": { "ws": false, @@ -64,7 +64,7 @@ "babel-preset-es2015": "^6.24.1", "babel-preset-es2015-generators-async": "^6.3.13", "browserify": "^13.1.0", - "esdoc": "^0.4.3", + "esdoc": "^1.1.0", "mocha": "^2.5.3", "uglifyjs": "^2.4.10" }