PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/@bitgo/sdk-coin-near/dist/src/lib
Просмотр файла: transaction.js
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Transaction = void 0;
const bs58_1 = __importDefault(require("bs58"));
const js_sha256_1 = require("js-sha256");
const nearAPI = __importStar(require("near-api-js"));
const transaction_1 = require("near-api-js/lib/transaction");
const crypto_1 = require("@near-js/crypto");
const transactions_1 = require("@near-js/transactions");
const sdk_core_1 = require("@bitgo/sdk-core");
const constants_1 = require("./constants");
const keyPair_1 = require("./keyPair");
const utils_1 = __importDefault(require("./utils"));
class Transaction extends sdk_core_1.BaseTransaction {
constructor(coinConfig) {
super(coinConfig);
}
get nearTransaction() {
return this._nearTransaction;
}
set nearTransaction(tx) {
this._nearTransaction = tx;
this._id = utils_1.default.base58Encode(this.getTransactionHash());
}
/** @inheritdoc */
canSign(key) {
try {
new keyPair_1.KeyPair({ prv: key.key });
return true;
}
catch {
return false;
}
}
/** @inheritdoc */
toBroadcastFormat() {
if (!this._nearTransaction) {
throw new sdk_core_1.InvalidTransactionError('Empty transaction data');
}
const txSeralized = this._nearSignedTransaction
? Buffer.from(this._nearSignedTransaction.encode()).toString('base64')
: Buffer.from(this._nearTransaction.encode()).toString('base64');
return txSeralized;
}
/** @inheritdoc */
toJson() {
if (!this._nearTransaction) {
throw new sdk_core_1.InvalidTransactionError('Empty transaction data');
}
const parsedActions = [];
const actions = this._nearTransaction.actions;
actions.map((action) => {
let parsedAction = {};
if (action.enum === 'transfer' && action.transfer) {
parsedAction = { transfer: action.transfer };
}
else if (action.enum === 'functionCall' && action.functionCall) {
const functionCall = action.functionCall;
parsedAction = {
functionCall: {
methodName: functionCall.methodName,
args: JSON.parse(Buffer.from(functionCall.args).toString()),
gas: functionCall.gas.toString(),
deposit: functionCall.deposit.toString(),
},
};
}
parsedActions.push(parsedAction);
});
let signature;
if (this._nearSignedTransaction?.signature?.ed25519Signature) {
signature = {
keyType: crypto_1.KeyType.ED25519,
data: new Uint8Array(this._nearSignedTransaction.signature.ed25519Signature.data),
};
}
let publicKey;
if (this._nearTransaction.publicKey?.ed25519Key) {
const rawBytes = new Uint8Array(this._nearTransaction.publicKey.ed25519Key.data);
const encoded = nearAPI.utils.serialize.base_encode(rawBytes);
publicKey = `ed25519:${encoded}`;
}
return {
id: this._id,
signerId: this._nearTransaction.signerId,
publicKey: publicKey,
nonce: this._nearTransaction.nonce,
receiverId: this._nearTransaction.receiverId,
actions: parsedActions,
signature: signature ? signature : undefined,
};
}
/**
* Set the transaction type.
*
* @param {TransactionType} transactionType The transaction type to be set.
*/
setTransactionType(transactionType) {
this._type = transactionType;
}
/**
* Sets this transaction payload
*
* @param rawTx
*/
fromRawTransaction(rawTx) {
const bufferRawTransaction = constants_1.HEX_REGEX.test(rawTx) ? Buffer.from(rawTx, 'hex') : Buffer.from(rawTx, 'base64');
try {
const signedTx = nearAPI.utils.serialize.deserialize(nearAPI.transactions.SCHEMA.SignedTransaction, bufferRawTransaction);
signedTx.transaction.actions = signedTx.transaction.actions.map((a) => {
const action = new transactions_1.Action(a);
switch (action.enum) {
case 'transfer': {
if (action.transfer?.deposit) {
return (0, transaction_1.transfer)(BigInt(action.transfer.deposit));
}
break;
}
case 'functionCall': {
if (action.functionCall) {
return (0, transaction_1.functionCall)(action.functionCall.methodName, new Uint8Array(action.functionCall.args), BigInt(action.functionCall.gas), BigInt(action.functionCall.deposit));
}
break;
}
}
return action;
});
this._nearSignedTransaction = signedTx;
this._nearTransaction = signedTx.transaction;
this._id = utils_1.default.base58Encode(this.getTransactionHash());
}
catch (e) {
try {
const unsignedTx = nearAPI.utils.serialize.deserialize(nearAPI.transactions.SCHEMA.Transaction, bufferRawTransaction);
unsignedTx.actions = unsignedTx.actions.map((a) => {
const action = new transactions_1.Action(a);
switch (action.enum) {
case 'transfer': {
if (action.transfer?.deposit) {
return (0, transaction_1.transfer)(BigInt(action.transfer.deposit));
}
break;
}
case 'functionCall': {
if (action.functionCall) {
return (0, transaction_1.functionCall)(action.functionCall.methodName, new Uint8Array(action.functionCall.args), BigInt(action.functionCall.gas), BigInt(action.functionCall.deposit));
}
break;
}
}
return action;
});
this._nearTransaction = unsignedTx;
this._id = utils_1.default.base58Encode(this.getTransactionHash());
}
catch (e) {
throw new sdk_core_1.InvalidTransactionError('unable to build transaction from raw');
}
}
this.loadInputsAndOutputs();
}
/**
* Sign this transaction
*
* @param {KeyPair} signer key
*/
sign(signer) {
if (!this._nearTransaction) {
throw new sdk_core_1.InvalidTransactionError('empty transaction to sign');
}
const serializedTxHash = this.getTransactionHash();
const signature = signer.signMessageinUint8Array(serializedTxHash);
this._nearSignedTransaction = new nearAPI.transactions.SignedTransaction({
transaction: this._nearTransaction,
signature: new nearAPI.transactions.Signature({
keyType: this._nearTransaction.publicKey.keyType,
data: signature,
}),
});
this.loadInputsAndOutputs();
}
/**
* set transaction type by staking contract method names.
* @param methodName method name to match and set the transaction type
*/
setTypeByFunctionCall(methodName) {
switch (methodName) {
case constants_1.StakingContractMethodNames.DepositAndStake:
this.setTransactionType(sdk_core_1.TransactionType.StakingActivate);
break;
case constants_1.StakingContractMethodNames.Unstake:
this.setTransactionType(sdk_core_1.TransactionType.StakingDeactivate);
break;
case constants_1.StakingContractMethodNames.Withdraw:
this.setTransactionType(sdk_core_1.TransactionType.StakingWithdraw);
break;
case constants_1.FT_TRANSFER:
this.setTransactionType(sdk_core_1.TransactionType.Send);
break;
case constants_1.STORAGE_DEPOSIT:
this.setTransactionType(sdk_core_1.TransactionType.StorageDeposit);
break;
}
}
/**
* Check if method is allowed on Near account-lib implementation.
* This method should check on all contracts added to Near.
* @param methodName contract call method name to check if it's allowed.
*/
validateMethodAllowed(methodName) {
const allowedMethods = [...Object.values(constants_1.StakingContractMethodNames), ...constants_1.FUNGIBLE_TOKEN_RELATED_METHODS];
if (!allowedMethods.includes(methodName)) {
throw new sdk_core_1.InvalidTransactionError('unsupported function call in raw transaction');
}
}
/**
* Check if valid methods are present for batching of actions
*
* @param {TxAction[]} actions list of near transaction actions
* @returns {void}
*/
validateBatchingMethods(actions) {
actions.every((action) => {
if (action.enum !== 'functionCall' || !action.functionCall) {
throw new sdk_core_1.InvalidTransactionError('invalid action for batching');
}
});
if (actions[0].functionCall?.methodName !== constants_1.STORAGE_DEPOSIT ||
actions[1].functionCall?.methodName !== constants_1.FT_TRANSFER) {
throw new sdk_core_1.InvalidTransactionError('invalid action sequence: expected storage_deposit followed by ft_transfer');
}
}
/**
* Build input and output field for this transaction
*
*/
loadInputsAndOutputs() {
if (!this._nearTransaction.actions || !this._nearTransaction.actions.length) {
throw new sdk_core_1.InvalidTransactionError('no actions in raw transaction');
}
// TODO: modify this for send-many support
// currently only storage deposit + ft transfer are allowed for batching
if (this._nearTransaction.actions.length > 2) {
throw new sdk_core_1.InvalidTransactionError('too many actions in raw transaction');
}
// check for correct sequence of actions
if (this._nearTransaction.actions.length === 2) {
this.validateBatchingMethods(this._nearTransaction.actions);
}
const action = this._nearTransaction.actions[0];
const actions = this._nearTransaction.actions;
switch (action.enum) {
case 'transfer':
this.setTransactionType(sdk_core_1.TransactionType.Send);
break;
case 'functionCall':
if (action.functionCall) {
const methodName = action.functionCall.methodName;
this.validateMethodAllowed(methodName);
this.setTypeByFunctionCall(methodName);
}
break;
default:
throw new sdk_core_1.InvalidTransactionError('unsupported action in raw transaction');
}
// if there are 2 actions, we know for sure that it is storage deposit + ft transfer
if (actions.length === 2) {
this.setTransactionType(sdk_core_1.TransactionType.Send);
}
const outputs = [];
const inputs = [];
actions.map((action) => {
switch (this.type) {
case sdk_core_1.TransactionType.Send:
if (action.transfer) {
const amount = action.transfer.deposit.toString();
inputs.push({
address: this._nearTransaction.signerId,
value: amount,
coin: this._coinConfig.name,
});
outputs.push({
address: this._nearTransaction.receiverId,
value: amount,
coin: this._coinConfig.name,
});
}
else if (action.functionCall) {
if (action.functionCall.methodName === 'ft_transfer') {
const parsedArgs = JSON.parse(Buffer.from(action.functionCall.args).toString());
inputs.push({
address: this._nearTransaction.signerId,
value: parsedArgs.amount,
coin: this._coinConfig.name,
});
outputs.push({
address: parsedArgs.receiver_id,
value: parsedArgs.amount,
coin: this._coinConfig.name,
});
}
}
break;
case sdk_core_1.TransactionType.StakingActivate:
if (action.functionCall) {
const stakingAmount = action.functionCall.deposit.toString();
inputs.push({
address: this._nearTransaction.signerId,
value: stakingAmount,
coin: this._coinConfig.name,
});
outputs.push({
address: this._nearTransaction.receiverId,
value: stakingAmount,
coin: this._coinConfig.name,
});
}
break;
case sdk_core_1.TransactionType.StakingWithdraw:
if (action.functionCall) {
const stakingWithdrawAmount = JSON.parse(Buffer.from(action.functionCall.args).toString()).amount;
inputs.push({
address: this._nearTransaction.receiverId,
value: stakingWithdrawAmount,
coin: this._coinConfig.name,
});
outputs.push({
address: this._nearTransaction.signerId,
value: stakingWithdrawAmount,
coin: this._coinConfig.name,
});
}
break;
case sdk_core_1.TransactionType.StorageDeposit:
break;
}
});
this._outputs = outputs;
this._inputs = inputs;
}
/**
* Returns a complete explanation for a transfer transaction
* @param {TxData} json The transaction data in json format
* @param {TransactionExplanation} explanationResult The transaction explanation to be completed
* @returns {TransactionExplanation}
*/
explainTransferTransaction(json, explanationResult) {
return {
...explanationResult,
outputAmount: json.actions[0].transfer?.deposit.toString() || '',
outputs: [
{
address: json.receiverId,
amount: json.actions[0].transfer?.deposit.toString() || '',
},
],
};
}
/**
* Returns a complete explanation for a staking activate transaction
* @param {TxData} json The transaction data in json format
* @param {TransactionExplanation} explanationResult The transaction explanation to be completed
* @returns {TransactionExplanation}
*/
explainStakingActivateTransaction(json, explanationResult) {
return {
...explanationResult,
outputAmount: json.actions[0].functionCall?.deposit.toString() || '',
outputs: [
{
address: json.receiverId,
amount: json.actions[0].functionCall?.deposit.toString() || '',
},
],
};
}
/**
* Returns a complete explanation for a staking withdraw transaction
* @param {TxData} json The transaction data in json format
* @param {TransactionExplanation} explanationResult The transaction explanation to be completed
* @returns {TransactionExplanation}
*/
explainStakingWithdrawTransaction(json, explanationResult) {
const amount = json.actions[0].functionCall?.args.amount;
return {
...explanationResult,
outputAmount: amount,
outputs: [
{
address: json.signerId,
amount: amount,
},
],
};
}
/**
* Calculates the total fungible token amount & total native near amount
*
* @param {Action[]} actions the list of delegate transaction actions
* @returns {String} either native near amount or fungible token amount
*/
calculateTotalOutputAmount(actions) {
let hasFtTransfer = false;
let hasStorageDeposit = false;
let totalTokenAmount = BigInt(0);
let totalNearDeposit = BigInt(0);
for (const action of actions) {
if (action.functionCall) {
const functionCall = action.functionCall;
const methodName = functionCall.methodName;
const args = functionCall.args;
const deposit = BigInt(functionCall.deposit);
if (methodName === constants_1.FT_TRANSFER) {
hasFtTransfer = true;
const amountStr = args['amount'];
if (args.amount) {
totalTokenAmount += BigInt(amountStr);
}
}
if (methodName === constants_1.STORAGE_DEPOSIT) {
hasStorageDeposit = true;
totalNearDeposit += deposit;
}
}
}
if (hasFtTransfer) {
return totalTokenAmount.toString();
}
else if (hasStorageDeposit) {
return totalNearDeposit.toString();
}
return '';
}
/**
* Returns a complete explanation for a token transfer transaction
* @param {TxData} json The transaction data in json format
* @param {TransactionExplanation} explanationResult The transaction explanation to be completed
* @returns {TransactionExplanation}
*/
explainTokenTransferTransaction(json, explanationResult) {
const actions = json.actions;
const outputAmount = this.calculateTotalOutputAmount(actions);
const outputs = [];
actions.map((action) => {
if (action.functionCall) {
const functionCall = action.functionCall;
if (functionCall.methodName === constants_1.FT_TRANSFER) {
const amountStr = functionCall.args['amount'];
const receiverId = functionCall.args['receiver_id'];
// in ft transfer, the outer receiver id will be contract address of the token
const tokenName = utils_1.default.findTokenNameFromContractAddress(json.receiverId);
const output = {
address: receiverId,
amount: amountStr,
};
if (tokenName) {
output.tokenName = tokenName;
}
outputs.push(output);
}
}
});
return {
...explanationResult,
outputAmount: outputAmount,
outputs: outputs,
};
}
/**
* Returns a complete explanation for a storage deposit transaction
* @param {TxData} json The transaction data in json format
* @param {TransactionExplanation} explanationResult The transaction explanation to be completed
* @returns {TransactionExplanation}
*/
explainStorageDepositTransaction(json, explanationResult) {
const actions = json.actions;
const outputAmount = this.calculateTotalOutputAmount(actions);
const outputs = [];
actions.map((action) => {
if (action.functionCall) {
const functionCall = action.functionCall;
if (functionCall.methodName === constants_1.STORAGE_DEPOSIT) {
const receiverId = functionCall.args && functionCall.args['account_id']
? functionCall.args['account_id']
: json.signerId;
// in storage deposit, the outer receiver id will be contract address of the token
const tokenName = utils_1.default.findTokenNameFromContractAddress(json.receiverId);
const output = {
address: receiverId,
amount: functionCall.deposit,
};
if (tokenName) {
output.tokenName = tokenName;
}
outputs.push(output);
}
}
});
return {
...explanationResult,
outputAmount: outputAmount,
outputs: outputs,
};
}
/** @inheritdoc */
explainTransaction() {
const result = this.toJson();
const displayOrder = ['outputAmount', 'changeAmount', 'outputs', 'changeOutputs', 'fee', 'type'];
const outputs = [];
const explanationResult = {
// txhash used to identify the transactions
id: result.id || '',
displayOrder,
outputAmount: '0',
changeAmount: '0',
changeOutputs: [],
outputs,
fee: { fee: '' },
type: this.type,
};
switch (this.type) {
case sdk_core_1.TransactionType.Send:
if (result.actions.length > 1 || result.actions[0].functionCall) {
return this.explainTokenTransferTransaction(result, explanationResult);
}
return this.explainTransferTransaction(result, explanationResult);
case sdk_core_1.TransactionType.StakingActivate:
return this.explainStakingActivateTransaction(result, explanationResult);
case sdk_core_1.TransactionType.StakingDeactivate:
return explanationResult;
case sdk_core_1.TransactionType.StakingWithdraw:
return this.explainStakingWithdrawTransaction(result, explanationResult);
case sdk_core_1.TransactionType.StorageDeposit:
return this.explainStorageDepositTransaction(result, explanationResult);
default:
throw new sdk_core_1.InvalidTransactionError('Transaction type not supported');
}
}
getTransactionHash() {
const serializedTx = nearAPI.utils.serialize.serialize(nearAPI.transactions.SCHEMA.Transaction, this._nearTransaction);
return new Uint8Array(js_sha256_1.sha256.array(serializedTx));
}
get signablePayload() {
if (!this._nearTransaction) {
throw new sdk_core_1.InvalidTransactionError('empty transaction');
}
return Buffer.from(this.getTransactionHash());
}
/**
* Constructs a signed payload using construct.signTx
* This method will be called during the build step if a TSS signature
* is added and will set the signTransaction which is the txHex that will be broadcasted
* As well as add the signature used to sign to the signature array in hex format
*
* @param {Buffer} signature The signature to be added to a near transaction
*/
constructSignedPayload(signature) {
this._nearSignedTransaction = new nearAPI.transactions.SignedTransaction({
transaction: this._nearTransaction,
signature: new nearAPI.transactions.Signature({
keyType: this._nearTransaction.publicKey.keyType,
data: signature,
}),
});
this.loadInputsAndOutputs();
}
/** @inheritdoc **/
get signature() {
const signatures = [];
if (this._nearSignedTransaction && this._nearSignedTransaction.signature.ed25519Signature) {
signatures.push(bs58_1.default.encode(this._nearSignedTransaction.signature.ed25519Signature.data));
}
return signatures;
}
}
exports.Transaction = Transaction;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidHJhbnNhY3Rpb24uanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvbGliL3RyYW5zYWN0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLGdEQUEwQjtBQUMxQix5Q0FBbUM7QUFDbkMscURBQXVDO0FBQ3ZDLDZEQUFxRTtBQUNyRSw0Q0FBMEM7QUFDMUMsd0RBQWtIO0FBRWxILDhDQVF5QjtBQUd6QiwyQ0FNcUI7QUFFckIsdUNBQW9DO0FBQ3BDLG9EQUE0QjtBQUU1QixNQUFhLFdBQVksU0FBUSwwQkFBZTtJQUk5QyxZQUFZLFVBQWdDO1FBQzFDLEtBQUssQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNwQixDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLGdCQUFnQixDQUFDO0lBQy9CLENBQUM7SUFFRCxJQUFJLGVBQWUsQ0FBQyxFQUFvQztRQUN0RCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsRUFBRSxDQUFDO1FBQzNCLElBQUksQ0FBQyxHQUFHLEdBQUcsZUFBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO0lBQzNELENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsT0FBTyxDQUFDLEdBQVk7UUFDbEIsSUFBSSxDQUFDO1lBQ0gsSUFBSSxpQkFBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDO1lBQzlCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUFDLE1BQU0sQ0FBQztZQUNQLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztJQUNILENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsaUJBQWlCO1FBQ2YsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzNCLE1BQU0sSUFBSSxrQ0FBdUIsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDO1FBQzlELENBQUM7UUFDRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsc0JBQXNCO1lBQzdDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7WUFDdEUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBQ25FLE9BQU8sV0FBVyxDQUFDO0lBQ3JCLENBQUM7SUFFRCxrQkFBa0I7SUFDbEIsTUFBTTtRQUNKLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksa0NBQXVCLENBQUMsd0JBQXdCLENBQUMsQ0FBQztRQUM5RCxDQUFDO1FBRUQsTUFBTSxhQUFhLEdBQWEsRUFBRSxDQUFDO1FBQ25DLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUM7UUFDOUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3JCLElBQUksWUFBWSxHQUFXLEVBQUUsQ0FBQztZQUM5QixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssVUFBVSxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDbEQsWUFBWSxHQUFHLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQztZQUMvQyxDQUFDO2lCQUFNLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxjQUFjLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUNqRSxNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDO2dCQUN6QyxZQUFZLEdBQUc7b0JBQ2IsWUFBWSxFQUFFO3dCQUNaLFVBQVUsRUFBRSxZQUFZLENBQUMsVUFBVTt3QkFDbkMsSUFBSSxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUM7d0JBQzNELEdBQUcsRUFBRSxZQUFZLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRTt3QkFDaEMsT0FBTyxFQUFFLFlBQVksQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFO3FCQUN6QztpQkFDRixDQUFDO1lBQ0osQ0FBQztZQUNELGFBQWEsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDbkMsQ0FBQyxDQUFDLENBQUM7UUFFSCxJQUFJLFNBQWdDLENBQUM7UUFDckMsSUFBSSxJQUFJLENBQUMsc0JBQXNCLEVBQUUsU0FBUyxFQUFFLGdCQUFnQixFQUFFLENBQUM7WUFDN0QsU0FBUyxHQUFHO2dCQUNWLE9BQU8sRUFBRSxnQkFBTyxDQUFDLE9BQU87Z0JBQ3hCLElBQUksRUFBRSxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQzthQUNsRixDQUFDO1FBQ0osQ0FBQztRQUNELElBQUksU0FBNkIsQ0FBQztRQUNsQyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsVUFBVSxFQUFFLENBQUM7WUFDaEQsTUFBTSxRQUFRLEdBQUcsSUFBSSxVQUFVLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDakYsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQzlELFNBQVMsR0FBRyxXQUFXLE9BQU8sRUFBRSxDQUFDO1FBQ25DLENBQUM7UUFFRCxPQUFPO1lBQ0wsRUFBRSxFQUFFLElBQUksQ0FBQyxHQUFHO1lBQ1osUUFBUSxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFRO1lBQ3hDLFNBQVMsRUFBRSxTQUFTO1lBQ3BCLEtBQUssRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsS0FBSztZQUNsQyxVQUFVLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFVBQVU7WUFDNUMsT0FBTyxFQUFFLGFBQWE7WUFDdEIsU0FBUyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxTQUFTO1NBQzdDLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7T0FJRztJQUNILGtCQUFrQixDQUFDLGVBQWdDO1FBQ2pELElBQUksQ0FBQyxLQUFLLEdBQUcsZUFBZSxDQUFDO0lBQy9CLENBQUM7SUFFRDs7OztPQUlHO0lBQ0gsa0JBQWtCLENBQUMsS0FBYTtRQUM5QixNQUFNLG9CQUFvQixHQUFHLHFCQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDOUcsSUFBSSxDQUFDO1lBQ0gsTUFBTSxRQUFRLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsV0FBVyxDQUNsRCxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsRUFDN0Msb0JBQW9CLENBQ0EsQ0FBQztZQUN2QixRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtnQkFDcEUsTUFBTSxNQUFNLEdBQUcsSUFBSSxxQkFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMvQixRQUFRLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztvQkFDcEIsS0FBSyxVQUFVLENBQUMsQ0FBQyxDQUFDO3dCQUNoQixJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUUsT0FBTyxFQUFFLENBQUM7NEJBQzdCLE9BQU8sSUFBQSxzQkFBUSxFQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7d0JBQ25ELENBQUM7d0JBQ0QsTUFBTTtvQkFDUixDQUFDO29CQUNELEtBQUssY0FBYyxDQUFDLENBQUMsQ0FBQzt3QkFDcEIsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7NEJBQ3hCLE9BQU8sSUFBQSwwQkFBWSxFQUNqQixNQUFNLENBQUMsWUFBWSxDQUFDLFVBQVUsRUFDOUIsSUFBSSxVQUFVLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsRUFDeEMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEVBQy9CLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLE9BQU8sQ0FBQyxDQUNwQyxDQUFDO3dCQUNKLENBQUM7d0JBQ0QsTUFBTTtvQkFDUixDQUFDO2dCQUNILENBQUM7Z0JBQ0QsT0FBTyxNQUFNLENBQUM7WUFDaEIsQ0FBQyxDQUFDLENBQUM7WUFDSCxJQUFJLENBQUMsc0JBQXNCLEdBQUcsUUFBUSxDQUFDO1lBQ3ZDLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsV0FBVyxDQUFDO1lBQzdDLElBQUksQ0FBQyxHQUFHLEdBQUcsZUFBSyxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsa0JBQWtCLEVBQUUsQ0FBQyxDQUFDO1FBQzNELENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1gsSUFBSSxDQUFDO2dCQUNILE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxLQUFLLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FDcEQsT0FBTyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsV0FBVyxFQUN2QyxvQkFBb0IsQ0FDRSxDQUFDO2dCQUN6QixVQUFVLENBQUMsT0FBTyxHQUFHLFVBQVUsQ0FBQyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUU7b0JBQ2hELE1BQU0sTUFBTSxHQUFHLElBQUkscUJBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQztvQkFDL0IsUUFBUSxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7d0JBQ3BCLEtBQUssVUFBVSxDQUFDLENBQUMsQ0FBQzs0QkFDaEIsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxDQUFDO2dDQUM3QixPQUFPLElBQUEsc0JBQVEsRUFBQyxNQUFNLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDOzRCQUNuRCxDQUFDOzRCQUNELE1BQU07d0JBQ1IsQ0FBQzt3QkFDRCxLQUFLLGNBQWMsQ0FBQyxDQUFDLENBQUM7NEJBQ3BCLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dDQUN4QixPQUFPLElBQUEsMEJBQVksRUFDakIsTUFBTSxDQUFDLFlBQVksQ0FBQyxVQUFVLEVBQzlCLElBQUksVUFBVSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLEVBQ3hDLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxFQUMvQixNQUFNLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FDcEMsQ0FBQzs0QkFDSixDQUFDOzRCQUNELE1BQU07d0JBQ1IsQ0FBQztvQkFDSCxDQUFDO29CQUNELE9BQU8sTUFBTSxDQUFDO2dCQUNoQixDQUFDLENBQUMsQ0FBQztnQkFDSCxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsVUFBVSxDQUFDO2dCQUNuQyxJQUFJLENBQUMsR0FBRyxHQUFHLGVBQUssQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLGtCQUFrQixFQUFFLENBQUMsQ0FBQztZQUMzRCxDQUFDO1lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDWCxNQUFNLElBQUksa0NBQXVCLENBQUMsc0NBQXNDLENBQUMsQ0FBQztZQUM1RSxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0lBQzlCLENBQUM7SUFFRDs7OztPQUlHO0lBRUgsSUFBSSxDQUFDLE1BQWU7UUFDbEIsSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzNCLE1BQU0sSUFBSSxrQ0FBdUIsQ0FBQywyQkFBMkIsQ0FBQyxDQUFDO1FBQ2pFLENBQUM7UUFDRCxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1FBQ25ELE1BQU0sU0FBUyxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFDO1FBQ25FLElBQUksQ0FBQyxzQkFBc0IsR0FBRyxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsaUJBQWlCLENBQUM7WUFDdkUsV0FBVyxFQUFFLElBQUksQ0FBQyxnQkFBZ0I7WUFDbEMsU0FBUyxFQUFFLElBQUksT0FBTyxDQUFDLFlBQVksQ0FBQyxTQUFTLENBQUM7Z0JBQzVDLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsU0FBUyxDQUFDLE9BQU87Z0JBQ2hELElBQUksRUFBRSxTQUFTO2FBQ2hCLENBQUM7U0FDSCxDQUFDLENBQUM7UUFDSCxJQUFJLENBQUMsb0JBQW9CLEVBQUUsQ0FBQztJQUM5QixDQUFDO0lBRUQ7OztPQUdHO0lBQ0sscUJBQXFCLENBQUMsVUFBa0I7UUFDOUMsUUFBUSxVQUFVLEVBQUUsQ0FBQztZQUNuQixLQUFLLHNDQUEwQixDQUFDLGVBQWU7Z0JBQzdDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQywwQkFBZSxDQUFDLGVBQWUsQ0FBQyxDQUFDO2dCQUN6RCxNQUFNO1lBQ1IsS0FBSyxzQ0FBMEIsQ0FBQyxPQUFPO2dCQUNyQyxJQUFJLENBQUMsa0JBQWtCLENBQUMsMEJBQWUsQ0FBQyxpQkFBaUIsQ0FBQyxDQUFDO2dCQUMzRCxNQUFNO1lBQ1IsS0FBSyxzQ0FBMEIsQ0FBQyxRQUFRO2dCQUN0QyxJQUFJLENBQUMsa0JBQWtCLENBQUMsMEJBQWUsQ0FBQyxlQUFlLENBQUMsQ0FBQztnQkFDekQsTUFBTTtZQUNSLEtBQUssdUJBQVc7Z0JBQ2QsSUFBSSxDQUFDLGtCQUFrQixDQUFDLDBCQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQzlDLE1BQU07WUFDUixLQUFLLDJCQUFlO2dCQUNsQixJQUFJLENBQUMsa0JBQWtCLENBQUMsMEJBQWUsQ0FBQyxjQUFjLENBQUMsQ0FBQztnQkFDeEQsTUFBTTtRQUNWLENBQUM7SUFDSCxDQUFDO0lBRUQ7Ozs7T0FJRztJQUNLLHFCQUFxQixDQUFDLFVBQWtCO1FBQzlDLE1BQU0sY0FBYyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLHNDQUEwQixDQUFDLEVBQUUsR0FBRywwQ0FBOEIsQ0FBQyxDQUFDO1FBQ3pHLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLENBQUM7WUFDekMsTUFBTSxJQUFJLGtDQUF1QixDQUFDLDhDQUE4QyxDQUFDLENBQUM7UUFDcEYsQ0FBQztJQUNILENBQUM7SUFFRDs7Ozs7T0FLRztJQUNLLHVCQUF1QixDQUFDLE9BQW1CO1FBQ2pELE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUN2QixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssY0FBYyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUMzRCxNQUFNLElBQUksa0NBQXVCLENBQUMsNkJBQTZCLENBQUMsQ0FBQztZQUNuRSxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFDSCxJQUNFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsVUFBVSxLQUFLLDJCQUFlO1lBQ3ZELE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsVUFBVSxLQUFLLHVCQUFXLEVBQ25ELENBQUM7WUFDRCxNQUFNLElBQUksa0NBQXVCLENBQUMsMkVBQTJFLENBQUMsQ0FBQztRQUNqSCxDQUFDO0lBQ0gsQ0FBQztJQUVEOzs7T0FHRztJQUNILG9CQUFvQjtRQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDNUUsTUFBTSxJQUFJLGtDQUF1QixDQUFDLCtCQUErQixDQUFDLENBQUM7UUFDckUsQ0FBQztRQUNELDBDQUEwQztRQUMxQyx3RUFBd0U7UUFDeEUsSUFBSSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUM3QyxNQUFNLElBQUksa0NBQXVCLENBQUMscUNBQXFDLENBQUMsQ0FBQztRQUMzRSxDQUFDO1FBQ0Qsd0NBQXdDO1FBQ3hDLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDL0MsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM5RCxDQUFDO1FBRUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNoRCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsT0FBTyxDQUFDO1FBRTlDLFFBQVEsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ3BCLEtBQUssVUFBVTtnQkFDYixJQUFJLENBQUMsa0JBQWtCLENBQUMsMEJBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDOUMsTUFBTTtZQUNSLEtBQUssY0FBYztnQkFDakIsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7b0JBQ3hCLE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsVUFBVSxDQUFDO29CQUNsRCxJQUFJLENBQUMscUJBQXFCLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQ3ZDLElBQUksQ0FBQyxxQkFBcUIsQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDekMsQ0FBQztnQkFDRCxNQUFNO1lBQ1I7Z0JBQ0UsTUFBTSxJQUFJLGtDQUF1QixDQUFDLHVDQUF1QyxDQUFDLENBQUM7UUFDL0UsQ0FBQztRQUNELG9GQUFvRjtRQUNwRixJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDekIsSUFBSSxDQUFDLGtCQUFrQixDQUFDLDBCQUFlLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDaEQsQ0FBQztRQUVELE1BQU0sT0FBTyxHQUFZLEVBQUUsQ0FBQztRQUM1QixNQUFNLE1BQU0sR0FBWSxFQUFFLENBQUM7UUFDM0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3JCLFFBQVEsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO2dCQUNsQixLQUFLLDBCQUFlLENBQUMsSUFBSTtvQkFDdkIsSUFBSSxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUM7d0JBQ3BCLE1BQU0sTUFBTSxHQUFHLE1BQU0sQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO3dCQUNsRCxNQUFNLENBQUMsSUFBSSxDQUFDOzRCQUNWLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUTs0QkFDdkMsS0FBSyxFQUFFLE1BQU07NEJBQ2IsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSTt5QkFDNUIsQ0FBQyxDQUFDO3dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUM7NEJBQ1gsT0FBTyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxVQUFVOzRCQUN6QyxLQUFLLEVBQUUsTUFBTTs0QkFDYixJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJO3lCQUM1QixDQUFDLENBQUM7b0JBQ0wsQ0FBQzt5QkFBTSxJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQzt3QkFDL0IsSUFBSSxNQUFNLENBQUMsWUFBWSxDQUFDLFVBQVUsS0FBSyxhQUFhLEVBQUUsQ0FBQzs0QkFDckQsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQzs0QkFDaEYsTUFBTSxDQUFDLElBQUksQ0FBQztnQ0FDVixPQUFPLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFFBQVE7Z0NBQ3ZDLEtBQUssRUFBRSxVQUFVLENBQUMsTUFBTTtnQ0FDeEIsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSTs2QkFDNUIsQ0FBQyxDQUFDOzRCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUM7Z0NBQ1gsT0FBTyxFQUFFLFVBQVUsQ0FBQyxXQUFXO2dDQUMvQixLQUFLLEVBQUUsVUFBVSxDQUFDLE1BQU07Z0NBQ3hCLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUk7NkJBQzVCLENBQUMsQ0FBQzt3QkFDTCxDQUFDO29CQUNILENBQUM7b0JBQ0QsTUFBTTtnQkFDUixLQUFLLDBCQUFlLENBQUMsZUFBZTtvQkFDbEMsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7d0JBQ3hCLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxDQUFDO3dCQUM3RCxNQUFNLENBQUMsSUFBSSxDQUFDOzRCQUNWLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsUUFBUTs0QkFDdkMsS0FBSyxFQUFFLGFBQWE7NEJBQ3BCLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUk7eUJBQzVCLENBQUMsQ0FBQzt3QkFDSCxPQUFPLENBQUMsSUFBSSxDQUFDOzRCQUNYLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsVUFBVTs0QkFDekMsS0FBSyxFQUFFLGFBQWE7NEJBQ3BCLElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUk7eUJBQzVCLENBQUMsQ0FBQztvQkFDTCxDQUFDO29CQUNELE1BQU07Z0JBQ1IsS0FBSywwQkFBZSxDQUFDLGVBQWU7b0JBQ2xDLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO3dCQUN4QixNQUFNLHFCQUFxQixHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDO3dCQUNsRyxNQUFNLENBQUMsSUFBSSxDQUFDOzRCQUNWLE9BQU8sRUFBRSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsVUFBVTs0QkFDekMsS0FBSyxFQUFFLHFCQUFxQjs0QkFDNUIsSUFBSSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSTt5QkFDNUIsQ0FBQyxDQUFDO3dCQUNILE9BQU8sQ0FBQyxJQUFJLENBQUM7NEJBQ1gsT0FBTyxFQUFFLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxRQUFROzRCQUN2QyxLQUFLLEVBQUUscUJBQXFCOzRCQUM1QixJQUFJLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJO3lCQUM1QixDQUFDLENBQUM7b0JBQ0wsQ0FBQztvQkFDRCxNQUFNO2dCQUNSLEtBQUssMEJBQWUsQ0FBQyxjQUFjO29CQUNqQyxNQUFNO1lBQ1YsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLFFBQVEsR0FBRyxPQUFPLENBQUM7UUFDeEIsSUFBSSxDQUFDLE9BQU8sR0FBRyxNQUFNLENBQUM7SUFDeEIsQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsMEJBQTBCLENBQUMsSUFBWSxFQUFFLGlCQUF5QztRQUNoRixPQUFPO1lBQ0wsR0FBRyxpQkFBaUI7WUFDcEIsWUFBWSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFO1lBQ2hFLE9BQU8sRUFBRTtnQkFDUDtvQkFDRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVU7b0JBQ3hCLE1BQU0sRUFBRSxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUSxFQUFFLElBQUksRUFBRTtpQkFDM0Q7YUFDRjtTQUNGLENBQUM7SUFDSixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxpQ0FBaUMsQ0FBQyxJQUFZLEVBQUUsaUJBQXlDO1FBQ3ZGLE9BQU87WUFDTCxHQUFHLGlCQUFpQjtZQUNwQixZQUFZLEVBQUUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLEVBQUU7WUFDcEUsT0FBTyxFQUFFO2dCQUNQO29CQUNFLE9BQU8sRUFBRSxJQUFJLENBQUMsVUFBVTtvQkFDeEIsTUFBTSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxFQUFFLE9BQU8sQ0FBQyxRQUFRLEVBQUUsSUFBSSxFQUFFO2lCQUMvRDthQUNGO1NBQ0YsQ0FBQztJQUNKLENBQUM7SUFFRDs7Ozs7T0FLRztJQUNILGlDQUFpQyxDQUFDLElBQVksRUFBRSxpQkFBeUM7UUFDdkYsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxZQUFZLEVBQUUsSUFBSSxDQUFDLE1BQWdCLENBQUM7UUFDbkUsT0FBTztZQUNMLEdBQUcsaUJBQWlCO1lBQ3BCLFlBQVksRUFBRSxNQUFNO1lBQ3BCLE9BQU8sRUFBRTtnQkFDUDtvQkFDRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFFBQVE7b0JBQ3RCLE1BQU0sRUFBRSxNQUFNO2lCQUNmO2FBQ0Y7U0FDRixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsMEJBQTBCLENBQUMsT0FBaUI7UUFDMUMsSUFBSSxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzFCLElBQUksaUJBQWlCLEdBQUcsS0FBSyxDQUFDO1FBRTlCLElBQUksZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ2pDLElBQUksZ0JBQWdCLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBRWpDLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFLENBQUM7WUFDN0IsSUFBSSxNQUFNLENBQUMsWUFBWSxFQUFFLENBQUM7Z0JBQ3hCLE1BQU0sWUFBWSxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUM7Z0JBQ3pDLE1BQU0sVUFBVSxHQUFHLFlBQVksQ0FBQyxVQUFVLENBQUM7Z0JBQzNDLE1BQU0sSUFBSSxHQUFHLFlBQVksQ0FBQyxJQUFJLENBQUM7Z0JBQy9CLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxZQUFZLENBQUMsT0FBTyxDQUFDLENBQUM7Z0JBQzdDLElBQUksVUFBVSxLQUFLLHVCQUFXLEVBQUUsQ0FBQztvQkFDL0IsYUFBYSxHQUFHLElBQUksQ0FBQztvQkFDckIsTUFBTSxTQUFTLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBVyxDQUFDO29CQUMzQyxJQUFJLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQzt3QkFDaEIsZ0JBQWdCLElBQUksTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDO29CQUN4QyxDQUFDO2dCQUNILENBQUM7Z0JBQ0QsSUFBSSxVQUFVLEtBQUssMkJBQWUsRUFBRSxDQUFDO29CQUNuQyxpQkFBaUIsR0FBRyxJQUFJLENBQUM7b0JBQ3pCLGdCQUFnQixJQUFJLE9BQU8sQ0FBQztnQkFDOUIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixPQUFPLGdCQUFnQixDQUFDLFFBQVEsRUFBRSxDQUFDO1FBQ3JDLENBQUM7YUFBTSxJQUFJLGlCQUFpQixFQUFFLENBQUM7WUFDN0IsT0FBTyxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUNyQyxDQUFDO1FBQ0QsT0FBTyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCwrQkFBK0IsQ0FBQyxJQUFZLEVBQUUsaUJBQXlDO1FBQ3JGLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFDN0IsTUFBTSxZQUFZLEdBQUcsSUFBSSxDQUFDLDBCQUEwQixDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzlELE1BQU0sT0FBTyxHQUE0QixFQUFFLENBQUM7UUFDNUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFO1lBQ3JCLElBQUksTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFDO2dCQUN4QixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDO2dCQUN6QyxJQUFJLFlBQVksQ0FBQyxVQUFVLEtBQUssdUJBQVcsRUFBRSxDQUFDO29CQUM1QyxNQUFNLFNBQVMsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBVyxDQUFDO29CQUN4RCxNQUFNLFVBQVUsR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBVyxDQUFDO29CQUM5RCw4RUFBOEU7b0JBQzlFLE1BQU0sU0FBUyxHQUFHLGVBQUssQ0FBQyxnQ0FBZ0MsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7b0JBQzFFLE1BQU0sTUFBTSxHQUEwQjt3QkFDcEMsT0FBTyxFQUFFLFVBQVU7d0JBQ25CLE1BQU0sRUFBRSxTQUFTO3FCQUNsQixDQUFDO29CQUNGLElBQUksU0FBUyxFQUFFLENBQUM7d0JBQ2QsTUFBTSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7b0JBQy9CLENBQUM7b0JBQ0QsT0FBTyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQztnQkFDdkIsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILE9BQU87WUFDTCxHQUFHLGlCQUFpQjtZQUNwQixZQUFZLEVBQUUsWUFBWTtZQUMxQixPQUFPLEVBQUUsT0FBTztTQUNqQixDQUFDO0lBQ0osQ0FBQztJQUVEOzs7OztPQUtHO0lBQ0gsZ0NBQWdDLENBQUMsSUFBWSxFQUFFLGlCQUF5QztRQUN0RixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1FBQzdCLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQywwQkFBMEIsQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUM5RCxNQUFNLE9BQU8sR0FBNEIsRUFBRSxDQUFDO1FBQzVDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtZQUNyQixJQUFJLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQztnQkFDeEIsTUFBTSxZQUFZLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQztnQkFDekMsSUFBSSxZQUFZLENBQUMsVUFBVSxLQUFLLDJCQUFlLEVBQUUsQ0FBQztvQkFDaEQsTUFBTSxVQUFVLEdBQ2QsWUFBWSxDQUFDLElBQUksSUFBSSxZQUFZLENBQUMsSUFBSSxDQUFDLFlBQVksQ0FBQzt3QkFDbEQsQ0FBQyxDQUFFLFlBQVksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFZO3dCQUM3QyxDQUFDLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQztvQkFDcEIsa0ZBQWtGO29CQUNsRixNQUFNLFNBQVMsR0FBRyxlQUFLLENBQUMsZ0NBQWdDLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDO29CQUMxRSxNQUFNLE1BQU0sR0FBMEI7d0JBQ3BDLE9BQU8sRUFBRSxVQUFVO3dCQUNuQixNQUFNLEVBQUUsWUFBWSxDQUFDLE9BQU87cUJBQzdCLENBQUM7b0JBQ0YsSUFBSSxTQUFTLEVBQUUsQ0FBQzt3QkFDZCxNQUFNLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztvQkFDL0IsQ0FBQztvQkFDRCxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO2dCQUN2QixDQUFDO1lBQ0gsQ0FBQztRQUNILENBQUMsQ0FBQyxDQUFDO1FBQ0gsT0FBTztZQUNMLEdBQUcsaUJBQWlCO1lBQ3BCLFlBQVksRUFBRSxZQUFZO1lBQzFCLE9BQU8sRUFBRSxPQUFPO1NBQ2pCLENBQUM7SUFDSixDQUFDO0lBRUQsa0JBQWtCO0lBQ2xCLGtCQUFrQjtRQUNoQixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDN0IsTUFBTSxZQUFZLEdBQUcsQ0FBQyxjQUFjLEVBQUUsY0FBYyxFQUFFLFNBQVMsRUFBRSxlQUFlLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDO1FBQ2pHLE1BQU0sT0FBTyxHQUEyQixFQUFFLENBQUM7UUFDM0MsTUFBTSxpQkFBaUIsR0FBMkI7WUFDaEQsMkNBQTJDO1lBQzNDLEVBQUUsRUFBRSxNQUFNLENBQUMsRUFBRSxJQUFJLEVBQUU7WUFDbkIsWUFBWTtZQUNaLFlBQVksRUFBRSxHQUFHO1lBQ2pCLFlBQVksRUFBRSxHQUFHO1lBQ2pCLGFBQWEsRUFBRSxFQUFFO1lBQ2pCLE9BQU87WUFDUCxHQUFHLEVBQUUsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFO1lBQ2hCLElBQUksRUFBRSxJQUFJLENBQUMsSUFBSTtTQUNoQixDQUFDO1FBQ0YsUUFBUSxJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEIsS0FBSywwQkFBZSxDQUFDLElBQUk7Z0JBQ3ZCLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsWUFBWSxFQUFFLENBQUM7b0JBQ2hFLE9BQU8sSUFBSSxDQUFDLCtCQUErQixDQUFDLE1BQU0sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO2dCQUN6RSxDQUFDO2dCQUNELE9BQU8sSUFBSSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sRUFBRSxpQkFBaUIsQ0FBQyxDQUFDO1lBQ3BFLEtBQUssMEJBQWUsQ0FBQyxlQUFlO2dCQUNsQyxPQUFPLElBQUksQ0FBQyxpQ0FBaUMsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztZQUMzRSxLQUFLLDBCQUFlLENBQUMsaUJBQWlCO2dCQUNwQyxPQUFPLGlCQUFpQixDQUFDO1lBQzNCLEtBQUssMEJBQWUsQ0FBQyxlQUFlO2dCQUNsQyxPQUFPLElBQUksQ0FBQyxpQ0FBaUMsQ0FBQyxNQUFNLEVBQUUsaUJBQWlCLENBQUMsQ0FBQztZQUMzRSxLQUFLLDBCQUFlLENBQUMsY0FBYztnQkFDakMsT0FBTyxJQUFJLENBQUMsZ0NBQWdDLENBQUMsTUFBTSxFQUFFLGlCQUFpQixDQUFDLENBQUM7WUFDMUU7Z0JBQ0UsTUFBTSxJQUFJLGtDQUF1QixDQUFDLGdDQUFnQyxDQUFDLENBQUM7UUFDeEUsQ0FBQztJQUNILENBQUM7SUFFTyxrQkFBa0I7UUFDeEIsTUFBTSxZQUFZLEdBQUcsT0FBTyxDQUFDLEtBQUssQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUNwRCxPQUFPLENBQUMsWUFBWSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQ3ZDLElBQUksQ0FBQyxnQkFBZ0IsQ0FDdEIsQ0FBQztRQUNGLE9BQU8sSUFBSSxVQUFVLENBQUMsa0JBQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQztJQUNwRCxDQUFDO0lBRUQsSUFBSSxlQUFlO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksa0NBQXVCLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUN6RCxDQUFDO1FBQ0QsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDLENBQUM7SUFDaEQsQ0FBQztJQUVEOzs7Ozs7O09BT0c7SUFDSCxzQkFBc0IsQ0FBQyxTQUFpQjtRQUN0QyxJQUFJLENBQUMsc0JBQXNCLEdBQUcsSUFBSSxPQUFPLENBQUMsWUFBWSxDQUFDLGlCQUFpQixDQUFDO1lBQ3ZFLFdBQVcsRUFBRSxJQUFJLENBQUMsZ0JBQWdCO1lBQ2xDLFNBQVMsRUFBRSxJQUFJLE9BQU8sQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDO2dCQUM1QyxPQUFPLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxPQUFPO2dCQUNoRCxJQUFJLEVBQUUsU0FBUzthQUNoQixDQUFDO1NBQ0gsQ0FBQyxDQUFDO1FBQ0gsSUFBSSxDQUFDLG9CQUFvQixFQUFFLENBQUM7SUFDOUIsQ0FBQztJQUNELG1CQUFtQjtJQUNuQixJQUFJLFNBQVM7UUFDWCxNQUFNLFVBQVUsR0FBYSxFQUFFLENBQUM7UUFFaEMsSUFBSSxJQUFJLENBQUMsc0JBQXNCLElBQUksSUFBSSxDQUFDLHNCQUFzQixDQUFDLFNBQVMsQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO1lBQzFGLFVBQVUsQ0FBQyxJQUFJLENBQUMsY0FBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0JBQXNCLENBQUMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7UUFDOUYsQ0FBQztRQUVELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7Q0FDRjtBQXRtQkQsa0NBc21CQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBiYXNlNTggZnJvbSAnYnM1OCc7XG5pbXBvcnQgeyBzaGEyNTYgfSBmcm9tICdqcy1zaGEyNTYnO1xuaW1wb3J0ICogYXMgbmVhckFQSSBmcm9tICduZWFyLWFwaS1qcyc7XG5pbXBvcnQgeyBmdW5jdGlvbkNhbGwsIHRyYW5zZmVyIH0gZnJvbSAnbmVhci1hcGktanMvbGliL3RyYW5zYWN0aW9uJztcbmltcG9ydCB7IEtleVR5cGUgfSBmcm9tICdAbmVhci1qcy9jcnlwdG8nO1xuaW1wb3J0IHsgQWN0aW9uIGFzIFR4QWN0aW9uLCBTaWduZWRUcmFuc2FjdGlvbiwgVHJhbnNhY3Rpb24gYXMgVW5zaWduZWRUcmFuc2FjdGlvbiB9IGZyb20gJ0BuZWFyLWpzL3RyYW5zYWN0aW9ucyc7XG5cbmltcG9ydCB7XG4gIEJhc2VLZXksXG4gIEJhc2VUcmFuc2FjdGlvbixcbiAgRW50cnksXG4gIEludmFsaWRUcmFuc2FjdGlvbkVycm9yLFxuICBJVHJhbnNhY3Rpb25SZWNpcGllbnQsXG4gIFRyYW5zYWN0aW9uUmVjaXBpZW50LFxuICBUcmFuc2FjdGlvblR5cGUsXG59IGZyb20gJ0BiaXRnby9zZGstY29yZSc7XG5pbXBvcnQgeyBCYXNlQ29pbiBhcyBDb2luQ29uZmlnIH0gZnJvbSAnQGJpdGdvL3N0YXRpY3MnO1xuXG5pbXBvcnQge1xuICBGVF9UUkFOU0ZFUixcbiAgRlVOR0lCTEVfVE9LRU5fUkVMQVRFRF9NRVRIT0RTLFxuICBIRVhfUkVHRVgsXG4gIFN0YWtpbmdDb250cmFjdE1ldGhvZE5hbWVzLFxuICBTVE9SQUdFX0RFUE9TSVQsXG59IGZyb20gJy4vY29uc3RhbnRzJztcbmltcG9ydCB7IEFjdGlvbiwgU2lnbmF0dXJlLCBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uLCBUeERhdGEgfSBmcm9tICcuL2lmYWNlJztcbmltcG9ydCB7IEtleVBhaXIgfSBmcm9tICcuL2tleVBhaXInO1xuaW1wb3J0IHV0aWxzIGZyb20gJy4vdXRpbHMnO1xuXG5leHBvcnQgY2xhc3MgVHJhbnNhY3Rpb24gZXh0ZW5kcyBCYXNlVHJhbnNhY3Rpb24ge1xuICBwcml2YXRlIF9uZWFyVHJhbnNhY3Rpb246IG5lYXJBUEkudHJhbnNhY3Rpb25zLlRyYW5zYWN0aW9uO1xuICBwcml2YXRlIF9uZWFyU2lnbmVkVHJhbnNhY3Rpb246IG5lYXJBUEkudHJhbnNhY3Rpb25zLlNpZ25lZFRyYW5zYWN0aW9uO1xuXG4gIGNvbnN0cnVjdG9yKGNvaW5Db25maWc6IFJlYWRvbmx5PENvaW5Db25maWc+KSB7XG4gICAgc3VwZXIoY29pbkNvbmZpZyk7XG4gIH1cblxuICBnZXQgbmVhclRyYW5zYWN0aW9uKCk6IG5lYXJBUEkudHJhbnNhY3Rpb25zLlRyYW5zYWN0aW9uIHtcbiAgICByZXR1cm4gdGhpcy5fbmVhclRyYW5zYWN0aW9uO1xuICB9XG5cbiAgc2V0IG5lYXJUcmFuc2FjdGlvbih0eDogbmVhckFQSS50cmFuc2FjdGlvbnMuVHJhbnNhY3Rpb24pIHtcbiAgICB0aGlzLl9uZWFyVHJhbnNhY3Rpb24gPSB0eDtcbiAgICB0aGlzLl9pZCA9IHV0aWxzLmJhc2U1OEVuY29kZSh0aGlzLmdldFRyYW5zYWN0aW9uSGFzaCgpKTtcbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICBjYW5TaWduKGtleTogQmFzZUtleSk6IGJvb2xlYW4ge1xuICAgIHRyeSB7XG4gICAgICBuZXcgS2V5UGFpcih7IHBydjoga2V5LmtleSB9KTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2gge1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBAaW5oZXJpdGRvYyAqL1xuICB0b0Jyb2FkY2FzdEZvcm1hdCgpOiBzdHJpbmcge1xuICAgIGlmICghdGhpcy5fbmVhclRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0VtcHR5IHRyYW5zYWN0aW9uIGRhdGEnKTtcbiAgICB9XG4gICAgY29uc3QgdHhTZXJhbGl6ZWQgPSB0aGlzLl9uZWFyU2lnbmVkVHJhbnNhY3Rpb25cbiAgICAgID8gQnVmZmVyLmZyb20odGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uLmVuY29kZSgpKS50b1N0cmluZygnYmFzZTY0JylcbiAgICAgIDogQnVmZmVyLmZyb20odGhpcy5fbmVhclRyYW5zYWN0aW9uLmVuY29kZSgpKS50b1N0cmluZygnYmFzZTY0Jyk7XG4gICAgcmV0dXJuIHR4U2VyYWxpemVkO1xuICB9XG5cbiAgLyoqIEBpbmhlcml0ZG9jICovXG4gIHRvSnNvbigpOiBUeERhdGEge1xuICAgIGlmICghdGhpcy5fbmVhclRyYW5zYWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ0VtcHR5IHRyYW5zYWN0aW9uIGRhdGEnKTtcbiAgICB9XG5cbiAgICBjb25zdCBwYXJzZWRBY3Rpb25zOiBBY3Rpb25bXSA9IFtdO1xuICAgIGNvbnN0IGFjdGlvbnMgPSB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uYWN0aW9ucztcbiAgICBhY3Rpb25zLm1hcCgoYWN0aW9uKSA9PiB7XG4gICAgICBsZXQgcGFyc2VkQWN0aW9uOiBBY3Rpb24gPSB7fTtcbiAgICAgIGlmIChhY3Rpb24uZW51bSA9PT0gJ3RyYW5zZmVyJyAmJiBhY3Rpb24udHJhbnNmZXIpIHtcbiAgICAgICAgcGFyc2VkQWN0aW9uID0geyB0cmFuc2ZlcjogYWN0aW9uLnRyYW5zZmVyIH07XG4gICAgICB9IGVsc2UgaWYgKGFjdGlvbi5lbnVtID09PSAnZnVuY3Rpb25DYWxsJyAmJiBhY3Rpb24uZnVuY3Rpb25DYWxsKSB7XG4gICAgICAgIGNvbnN0IGZ1bmN0aW9uQ2FsbCA9IGFjdGlvbi5mdW5jdGlvbkNhbGw7XG4gICAgICAgIHBhcnNlZEFjdGlvbiA9IHtcbiAgICAgICAgICBmdW5jdGlvbkNhbGw6IHtcbiAgICAgICAgICAgIG1ldGhvZE5hbWU6IGZ1bmN0aW9uQ2FsbC5tZXRob2ROYW1lLFxuICAgICAgICAgICAgYXJnczogSlNPTi5wYXJzZShCdWZmZXIuZnJvbShmdW5jdGlvbkNhbGwuYXJncykudG9TdHJpbmcoKSksXG4gICAgICAgICAgICBnYXM6IGZ1bmN0aW9uQ2FsbC5nYXMudG9TdHJpbmcoKSxcbiAgICAgICAgICAgIGRlcG9zaXQ6IGZ1bmN0aW9uQ2FsbC5kZXBvc2l0LnRvU3RyaW5nKCksXG4gICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICAgIH1cbiAgICAgIHBhcnNlZEFjdGlvbnMucHVzaChwYXJzZWRBY3Rpb24pO1xuICAgIH0pO1xuXG4gICAgbGV0IHNpZ25hdHVyZTogU2lnbmF0dXJlIHwgdW5kZWZpbmVkO1xuICAgIGlmICh0aGlzLl9uZWFyU2lnbmVkVHJhbnNhY3Rpb24/LnNpZ25hdHVyZT8uZWQyNTUxOVNpZ25hdHVyZSkge1xuICAgICAgc2lnbmF0dXJlID0ge1xuICAgICAgICBrZXlUeXBlOiBLZXlUeXBlLkVEMjU1MTksXG4gICAgICAgIGRhdGE6IG5ldyBVaW50OEFycmF5KHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbi5zaWduYXR1cmUuZWQyNTUxOVNpZ25hdHVyZS5kYXRhKSxcbiAgICAgIH07XG4gICAgfVxuICAgIGxldCBwdWJsaWNLZXk6IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5fbmVhclRyYW5zYWN0aW9uLnB1YmxpY0tleT8uZWQyNTUxOUtleSkge1xuICAgICAgY29uc3QgcmF3Qnl0ZXMgPSBuZXcgVWludDhBcnJheSh0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucHVibGljS2V5LmVkMjU1MTlLZXkuZGF0YSk7XG4gICAgICBjb25zdCBlbmNvZGVkID0gbmVhckFQSS51dGlscy5zZXJpYWxpemUuYmFzZV9lbmNvZGUocmF3Qnl0ZXMpO1xuICAgICAgcHVibGljS2V5ID0gYGVkMjU1MTk6JHtlbmNvZGVkfWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIGlkOiB0aGlzLl9pZCxcbiAgICAgIHNpZ25lcklkOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uc2lnbmVySWQsXG4gICAgICBwdWJsaWNLZXk6IHB1YmxpY0tleSxcbiAgICAgIG5vbmNlOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ubm9uY2UsXG4gICAgICByZWNlaXZlcklkOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucmVjZWl2ZXJJZCxcbiAgICAgIGFjdGlvbnM6IHBhcnNlZEFjdGlvbnMsXG4gICAgICBzaWduYXR1cmU6IHNpZ25hdHVyZSA/IHNpZ25hdHVyZSA6IHVuZGVmaW5lZCxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgdHJhbnNhY3Rpb24gdHlwZS5cbiAgICpcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvblR5cGV9IHRyYW5zYWN0aW9uVHlwZSBUaGUgdHJhbnNhY3Rpb24gdHlwZSB0byBiZSBzZXQuXG4gICAqL1xuICBzZXRUcmFuc2FjdGlvblR5cGUodHJhbnNhY3Rpb25UeXBlOiBUcmFuc2FjdGlvblR5cGUpOiB2b2lkIHtcbiAgICB0aGlzLl90eXBlID0gdHJhbnNhY3Rpb25UeXBlO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhpcyB0cmFuc2FjdGlvbiBwYXlsb2FkXG4gICAqXG4gICAqIEBwYXJhbSByYXdUeFxuICAgKi9cbiAgZnJvbVJhd1RyYW5zYWN0aW9uKHJhd1R4OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBidWZmZXJSYXdUcmFuc2FjdGlvbiA9IEhFWF9SRUdFWC50ZXN0KHJhd1R4KSA/IEJ1ZmZlci5mcm9tKHJhd1R4LCAnaGV4JykgOiBCdWZmZXIuZnJvbShyYXdUeCwgJ2Jhc2U2NCcpO1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBzaWduZWRUeCA9IG5lYXJBUEkudXRpbHMuc2VyaWFsaXplLmRlc2VyaWFsaXplKFxuICAgICAgICBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TQ0hFTUEuU2lnbmVkVHJhbnNhY3Rpb24sXG4gICAgICAgIGJ1ZmZlclJhd1RyYW5zYWN0aW9uXG4gICAgICApIGFzIFNpZ25lZFRyYW5zYWN0aW9uO1xuICAgICAgc2lnbmVkVHgudHJhbnNhY3Rpb24uYWN0aW9ucyA9IHNpZ25lZFR4LnRyYW5zYWN0aW9uLmFjdGlvbnMubWFwKChhKSA9PiB7XG4gICAgICAgIGNvbnN0IGFjdGlvbiA9IG5ldyBUeEFjdGlvbihhKTtcbiAgICAgICAgc3dpdGNoIChhY3Rpb24uZW51bSkge1xuICAgICAgICAgIGNhc2UgJ3RyYW5zZmVyJzoge1xuICAgICAgICAgICAgaWYgKGFjdGlvbi50cmFuc2Zlcj8uZGVwb3NpdCkge1xuICAgICAgICAgICAgICByZXR1cm4gdHJhbnNmZXIoQmlnSW50KGFjdGlvbi50cmFuc2Zlci5kZXBvc2l0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY2FzZSAnZnVuY3Rpb25DYWxsJzoge1xuICAgICAgICAgICAgaWYgKGFjdGlvbi5mdW5jdGlvbkNhbGwpIHtcbiAgICAgICAgICAgICAgcmV0dXJuIGZ1bmN0aW9uQ2FsbChcbiAgICAgICAgICAgICAgICBhY3Rpb24uZnVuY3Rpb25DYWxsLm1ldGhvZE5hbWUsXG4gICAgICAgICAgICAgICAgbmV3IFVpbnQ4QXJyYXkoYWN0aW9uLmZ1bmN0aW9uQ2FsbC5hcmdzKSxcbiAgICAgICAgICAgICAgICBCaWdJbnQoYWN0aW9uLmZ1bmN0aW9uQ2FsbC5nYXMpLFxuICAgICAgICAgICAgICAgIEJpZ0ludChhY3Rpb24uZnVuY3Rpb25DYWxsLmRlcG9zaXQpXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGFjdGlvbjtcbiAgICAgIH0pO1xuICAgICAgdGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uID0gc2lnbmVkVHg7XG4gICAgICB0aGlzLl9uZWFyVHJhbnNhY3Rpb24gPSBzaWduZWRUeC50cmFuc2FjdGlvbjtcbiAgICAgIHRoaXMuX2lkID0gdXRpbHMuYmFzZTU4RW5jb2RlKHRoaXMuZ2V0VHJhbnNhY3Rpb25IYXNoKCkpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIHRyeSB7XG4gICAgICAgIGNvbnN0IHVuc2lnbmVkVHggPSBuZWFyQVBJLnV0aWxzLnNlcmlhbGl6ZS5kZXNlcmlhbGl6ZShcbiAgICAgICAgICBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TQ0hFTUEuVHJhbnNhY3Rpb24sXG4gICAgICAgICAgYnVmZmVyUmF3VHJhbnNhY3Rpb25cbiAgICAgICAgKSBhcyBVbnNpZ25lZFRyYW5zYWN0aW9uO1xuICAgICAgICB1bnNpZ25lZFR4LmFjdGlvbnMgPSB1bnNpZ25lZFR4LmFjdGlvbnMubWFwKChhKSA9PiB7XG4gICAgICAgICAgY29uc3QgYWN0aW9uID0gbmV3IFR4QWN0aW9uKGEpO1xuICAgICAgICAgIHN3aXRjaCAoYWN0aW9uLmVudW0pIHtcbiAgICAgICAgICAgIGNhc2UgJ3RyYW5zZmVyJzoge1xuICAgICAgICAgICAgICBpZiAoYWN0aW9uLnRyYW5zZmVyPy5kZXBvc2l0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRyYW5zZmVyKEJpZ0ludChhY3Rpb24udHJhbnNmZXIuZGVwb3NpdCkpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2FzZSAnZnVuY3Rpb25DYWxsJzoge1xuICAgICAgICAgICAgICBpZiAoYWN0aW9uLmZ1bmN0aW9uQ2FsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmdW5jdGlvbkNhbGwoXG4gICAgICAgICAgICAgICAgICBhY3Rpb24uZnVuY3Rpb25DYWxsLm1ldGhvZE5hbWUsXG4gICAgICAgICAgICAgICAgICBuZXcgVWludDhBcnJheShhY3Rpb24uZnVuY3Rpb25DYWxsLmFyZ3MpLFxuICAgICAgICAgICAgICAgICAgQmlnSW50KGFjdGlvbi5mdW5jdGlvbkNhbGwuZ2FzKSxcbiAgICAgICAgICAgICAgICAgIEJpZ0ludChhY3Rpb24uZnVuY3Rpb25DYWxsLmRlcG9zaXQpXG4gICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGFjdGlvbjtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuX25lYXJUcmFuc2FjdGlvbiA9IHVuc2lnbmVkVHg7XG4gICAgICAgIHRoaXMuX2lkID0gdXRpbHMuYmFzZTU4RW5jb2RlKHRoaXMuZ2V0VHJhbnNhY3Rpb25IYXNoKCkpO1xuICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ3VuYWJsZSB0byBidWlsZCB0cmFuc2FjdGlvbiBmcm9tIHJhdycpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMubG9hZElucHV0c0FuZE91dHB1dHMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTaWduIHRoaXMgdHJhbnNhY3Rpb25cbiAgICpcbiAgICogQHBhcmFtIHtLZXlQYWlyfSBzaWduZXIga2V5XG4gICAqL1xuXG4gIHNpZ24oc2lnbmVyOiBLZXlQYWlyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl9uZWFyVHJhbnNhY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBJbnZhbGlkVHJhbnNhY3Rpb25FcnJvcignZW1wdHkgdHJhbnNhY3Rpb24gdG8gc2lnbicpO1xuICAgIH1cbiAgICBjb25zdCBzZXJpYWxpemVkVHhIYXNoID0gdGhpcy5nZXRUcmFuc2FjdGlvbkhhc2goKTtcbiAgICBjb25zdCBzaWduYXR1cmUgPSBzaWduZXIuc2lnbk1lc3NhZ2VpblVpbnQ4QXJyYXkoc2VyaWFsaXplZFR4SGFzaCk7XG4gICAgdGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uID0gbmV3IG5lYXJBUEkudHJhbnNhY3Rpb25zLlNpZ25lZFRyYW5zYWN0aW9uKHtcbiAgICAgIHRyYW5zYWN0aW9uOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24sXG4gICAgICBzaWduYXR1cmU6IG5ldyBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TaWduYXR1cmUoe1xuICAgICAgICBrZXlUeXBlOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucHVibGljS2V5LmtleVR5cGUsXG4gICAgICAgIGRhdGE6IHNpZ25hdHVyZSxcbiAgICAgIH0pLFxuICAgIH0pO1xuICAgIHRoaXMubG9hZElucHV0c0FuZE91dHB1dHMoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBzZXQgdHJhbnNhY3Rpb24gdHlwZSBieSBzdGFraW5nIGNvbnRyYWN0IG1ldGhvZCBuYW1lcy5cbiAgICogQHBhcmFtIG1ldGhvZE5hbWUgbWV0aG9kIG5hbWUgdG8gbWF0Y2ggYW5kIHNldCB0aGUgdHJhbnNhY3Rpb24gdHlwZVxuICAgKi9cbiAgcHJpdmF0ZSBzZXRUeXBlQnlGdW5jdGlvbkNhbGwobWV0aG9kTmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgc3dpdGNoIChtZXRob2ROYW1lKSB7XG4gICAgICBjYXNlIFN0YWtpbmdDb250cmFjdE1ldGhvZE5hbWVzLkRlcG9zaXRBbmRTdGFrZTpcbiAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSBTdGFraW5nQ29udHJhY3RNZXRob2ROYW1lcy5VbnN0YWtlOlxuICAgICAgICB0aGlzLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0RlYWN0aXZhdGUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgU3Rha2luZ0NvbnRyYWN0TWV0aG9kTmFtZXMuV2l0aGRyYXc6XG4gICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXcpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgRlRfVFJBTlNGRVI6XG4gICAgICAgIHRoaXMuc2V0VHJhbnNhY3Rpb25UeXBlKFRyYW5zYWN0aW9uVHlwZS5TZW5kKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIFNUT1JBR0VfREVQT1NJVDpcbiAgICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlN0b3JhZ2VEZXBvc2l0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIG1ldGhvZCBpcyBhbGxvd2VkIG9uIE5lYXIgYWNjb3VudC1saWIgaW1wbGVtZW50YXRpb24uXG4gICAqIFRoaXMgbWV0aG9kIHNob3VsZCBjaGVjayBvbiBhbGwgY29udHJhY3RzIGFkZGVkIHRvIE5lYXIuXG4gICAqIEBwYXJhbSBtZXRob2ROYW1lIGNvbnRyYWN0IGNhbGwgbWV0aG9kIG5hbWUgdG8gY2hlY2sgaWYgaXQncyBhbGxvd2VkLlxuICAgKi9cbiAgcHJpdmF0ZSB2YWxpZGF0ZU1ldGhvZEFsbG93ZWQobWV0aG9kTmFtZTogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgYWxsb3dlZE1ldGhvZHMgPSBbLi4uT2JqZWN0LnZhbHVlcyhTdGFraW5nQ29udHJhY3RNZXRob2ROYW1lcyksIC4uLkZVTkdJQkxFX1RPS0VOX1JFTEFURURfTUVUSE9EU107XG4gICAgaWYgKCFhbGxvd2VkTWV0aG9kcy5pbmNsdWRlcyhtZXRob2ROYW1lKSkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCd1bnN1cHBvcnRlZCBmdW5jdGlvbiBjYWxsIGluIHJhdyB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB2YWxpZCBtZXRob2RzIGFyZSBwcmVzZW50IGZvciBiYXRjaGluZyBvZiBhY3Rpb25zXG4gICAqXG4gICAqIEBwYXJhbSB7VHhBY3Rpb25bXX0gYWN0aW9ucyBsaXN0IG9mIG5lYXIgdHJhbnNhY3Rpb24gYWN0aW9uc1xuICAgKiBAcmV0dXJucyB7dm9pZH1cbiAgICovXG4gIHByaXZhdGUgdmFsaWRhdGVCYXRjaGluZ01ldGhvZHMoYWN0aW9uczogVHhBY3Rpb25bXSk6IHZvaWQge1xuICAgIGFjdGlvbnMuZXZlcnkoKGFjdGlvbikgPT4ge1xuICAgICAgaWYgKGFjdGlvbi5lbnVtICE9PSAnZnVuY3Rpb25DYWxsJyB8fCAhYWN0aW9uLmZ1bmN0aW9uQ2FsbCkge1xuICAgICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ2ludmFsaWQgYWN0aW9uIGZvciBiYXRjaGluZycpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIGlmIChcbiAgICAgIGFjdGlvbnNbMF0uZnVuY3Rpb25DYWxsPy5tZXRob2ROYW1lICE9PSBTVE9SQUdFX0RFUE9TSVQgfHxcbiAgICAgIGFjdGlvbnNbMV0uZnVuY3Rpb25DYWxsPy5tZXRob2ROYW1lICE9PSBGVF9UUkFOU0ZFUlxuICAgICkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdpbnZhbGlkIGFjdGlvbiBzZXF1ZW5jZTogZXhwZWN0ZWQgc3RvcmFnZV9kZXBvc2l0IGZvbGxvd2VkIGJ5IGZ0X3RyYW5zZmVyJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEJ1aWxkIGlucHV0IGFuZCBvdXRwdXQgZmllbGQgZm9yIHRoaXMgdHJhbnNhY3Rpb25cbiAgICpcbiAgICovXG4gIGxvYWRJbnB1dHNBbmRPdXRwdXRzKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5fbmVhclRyYW5zYWN0aW9uLmFjdGlvbnMgfHwgIXRoaXMuX25lYXJUcmFuc2FjdGlvbi5hY3Rpb25zLmxlbmd0aCkge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdubyBhY3Rpb25zIGluIHJhdyB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgICAvLyBUT0RPOiBtb2RpZnkgdGhpcyBmb3Igc2VuZC1tYW55IHN1cHBvcnRcbiAgICAvLyBjdXJyZW50bHkgb25seSBzdG9yYWdlIGRlcG9zaXQgKyBmdCB0cmFuc2ZlciBhcmUgYWxsb3dlZCBmb3IgYmF0Y2hpbmdcbiAgICBpZiAodGhpcy5fbmVhclRyYW5zYWN0aW9uLmFjdGlvbnMubGVuZ3RoID4gMikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCd0b28gbWFueSBhY3Rpb25zIGluIHJhdyB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgICAvLyBjaGVjayBmb3IgY29ycmVjdCBzZXF1ZW5jZSBvZiBhY3Rpb25zXG4gICAgaWYgKHRoaXMuX25lYXJUcmFuc2FjdGlvbi5hY3Rpb25zLmxlbmd0aCA9PT0gMikge1xuICAgICAgdGhpcy52YWxpZGF0ZUJhdGNoaW5nTWV0aG9kcyh0aGlzLl9uZWFyVHJhbnNhY3Rpb24uYWN0aW9ucyk7XG4gICAgfVxuXG4gICAgY29uc3QgYWN0aW9uID0gdGhpcy5fbmVhclRyYW5zYWN0aW9uLmFjdGlvbnNbMF07XG4gICAgY29uc3QgYWN0aW9ucyA9IHRoaXMuX25lYXJUcmFuc2FjdGlvbi5hY3Rpb25zO1xuXG4gICAgc3dpdGNoIChhY3Rpb24uZW51bSkge1xuICAgICAgY2FzZSAndHJhbnNmZXInOlxuICAgICAgICB0aGlzLnNldFRyYW5zYWN0aW9uVHlwZShUcmFuc2FjdGlvblR5cGUuU2VuZCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnZnVuY3Rpb25DYWxsJzpcbiAgICAgICAgaWYgKGFjdGlvbi5mdW5jdGlvbkNhbGwpIHtcbiAgICAgICAgICBjb25zdCBtZXRob2ROYW1lID0gYWN0aW9uLmZ1bmN0aW9uQ2FsbC5tZXRob2ROYW1lO1xuICAgICAgICAgIHRoaXMudmFsaWRhdGVNZXRob2RBbGxvd2VkKG1ldGhvZE5hbWUpO1xuICAgICAgICAgIHRoaXMuc2V0VHlwZUJ5RnVuY3Rpb25DYWxsKG1ldGhvZE5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCd1bnN1cHBvcnRlZCBhY3Rpb24gaW4gcmF3IHRyYW5zYWN0aW9uJyk7XG4gICAgfVxuICAgIC8vIGlmIHRoZXJlIGFyZSAyIGFjdGlvbnMsIHdlIGtub3cgZm9yIHN1cmUgdGhhdCBpdCBpcyBzdG9yYWdlIGRlcG9zaXQgKyBmdCB0cmFuc2ZlclxuICAgIGlmIChhY3Rpb25zLmxlbmd0aCA9PT0gMikge1xuICAgICAgdGhpcy5zZXRUcmFuc2FjdGlvblR5cGUoVHJhbnNhY3Rpb25UeXBlLlNlbmQpO1xuICAgIH1cblxuICAgIGNvbnN0IG91dHB1dHM6IEVudHJ5W10gPSBbXTtcbiAgICBjb25zdCBpbnB1dHM6IEVudHJ5W10gPSBbXTtcbiAgICBhY3Rpb25zLm1hcCgoYWN0aW9uKSA9PiB7XG4gICAgICBzd2l0Y2ggKHRoaXMudHlwZSkge1xuICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kOlxuICAgICAgICAgIGlmIChhY3Rpb24udHJhbnNmZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGFtb3VudCA9IGFjdGlvbi50cmFuc2Zlci5kZXBvc2l0LnRvU3RyaW5nKCk7XG4gICAgICAgICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgICAgICAgIGFkZHJlc3M6IHRoaXMuX25lYXJUcmFuc2FjdGlvbi5zaWduZXJJZCxcbiAgICAgICAgICAgICAgdmFsdWU6IGFtb3VudCxcbiAgICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBvdXRwdXRzLnB1c2goe1xuICAgICAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucmVjZWl2ZXJJZCxcbiAgICAgICAgICAgICAgdmFsdWU6IGFtb3VudCxcbiAgICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIGlmIChhY3Rpb24uZnVuY3Rpb25DYWxsKSB7XG4gICAgICAgICAgICBpZiAoYWN0aW9uLmZ1bmN0aW9uQ2FsbC5tZXRob2ROYW1lID09PSAnZnRfdHJhbnNmZXInKSB7XG4gICAgICAgICAgICAgIGNvbnN0IHBhcnNlZEFyZ3MgPSBKU09OLnBhcnNlKEJ1ZmZlci5mcm9tKGFjdGlvbi5mdW5jdGlvbkNhbGwuYXJncykudG9TdHJpbmcoKSk7XG4gICAgICAgICAgICAgIGlucHV0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uc2lnbmVySWQsXG4gICAgICAgICAgICAgICAgdmFsdWU6IHBhcnNlZEFyZ3MuYW1vdW50LFxuICAgICAgICAgICAgICAgIGNvaW46IHRoaXMuX2NvaW5Db25maWcubmFtZSxcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgIG91dHB1dHMucHVzaCh7XG4gICAgICAgICAgICAgICAgYWRkcmVzczogcGFyc2VkQXJncy5yZWNlaXZlcl9pZCxcbiAgICAgICAgICAgICAgICB2YWx1ZTogcGFyc2VkQXJncy5hbW91bnQsXG4gICAgICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgVHJhbnNhY3Rpb25UeXBlLlN0YWtpbmdBY3RpdmF0ZTpcbiAgICAgICAgICBpZiAoYWN0aW9uLmZ1bmN0aW9uQ2FsbCkge1xuICAgICAgICAgICAgY29uc3Qgc3Rha2luZ0Ftb3VudCA9IGFjdGlvbi5mdW5jdGlvbkNhbGwuZGVwb3NpdC50b1N0cmluZygpO1xuICAgICAgICAgICAgaW5wdXRzLnB1c2goe1xuICAgICAgICAgICAgICBhZGRyZXNzOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24uc2lnbmVySWQsXG4gICAgICAgICAgICAgIHZhbHVlOiBzdGFraW5nQW1vdW50LFxuICAgICAgICAgICAgICBjb2luOiB0aGlzLl9jb2luQ29uZmlnLm5hbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIG91dHB1dHMucHVzaCh7XG4gICAgICAgICAgICAgIGFkZHJlc3M6IHRoaXMuX25lYXJUcmFuc2FjdGlvbi5yZWNlaXZlcklkLFxuICAgICAgICAgICAgICB2YWx1ZTogc3Rha2luZ0Ftb3VudCxcbiAgICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nV2l0aGRyYXc6XG4gICAgICAgICAgaWYgKGFjdGlvbi5mdW5jdGlvbkNhbGwpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0YWtpbmdXaXRoZHJhd0Ftb3VudCA9IEpTT04ucGFyc2UoQnVmZmVyLmZyb20oYWN0aW9uLmZ1bmN0aW9uQ2FsbC5hcmdzKS50b1N0cmluZygpKS5hbW91bnQ7XG4gICAgICAgICAgICBpbnB1dHMucHVzaCh7XG4gICAgICAgICAgICAgIGFkZHJlc3M6IHRoaXMuX25lYXJUcmFuc2FjdGlvbi5yZWNlaXZlcklkLFxuICAgICAgICAgICAgICB2YWx1ZTogc3Rha2luZ1dpdGhkcmF3QW1vdW50LFxuICAgICAgICAgICAgICBjb2luOiB0aGlzLl9jb2luQ29uZmlnLm5hbWUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIG91dHB1dHMucHVzaCh7XG4gICAgICAgICAgICAgIGFkZHJlc3M6IHRoaXMuX25lYXJUcmFuc2FjdGlvbi5zaWduZXJJZCxcbiAgICAgICAgICAgICAgdmFsdWU6IHN0YWtpbmdXaXRoZHJhd0Ftb3VudCxcbiAgICAgICAgICAgICAgY29pbjogdGhpcy5fY29pbkNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdG9yYWdlRGVwb3NpdDpcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9KTtcbiAgICB0aGlzLl9vdXRwdXRzID0gb3V0cHV0cztcbiAgICB0aGlzLl9pbnB1dHMgPSBpbnB1dHM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGNvbXBsZXRlIGV4cGxhbmF0aW9uIGZvciBhIHRyYW5zZmVyIHRyYW5zYWN0aW9uXG4gICAqIEBwYXJhbSB7VHhEYXRhfSBqc29uIFRoZSB0cmFuc2FjdGlvbiBkYXRhIGluIGpzb24gZm9ybWF0XG4gICAqIEBwYXJhbSB7VHJhbnNhY3Rpb25FeHBsYW5hdGlvbn0gZXhwbGFuYXRpb25SZXN1bHQgVGhlIHRyYW5zYWN0aW9uIGV4cGxhbmF0aW9uIHRvIGJlIGNvbXBsZXRlZFxuICAgKiBAcmV0dXJucyB7VHJhbnNhY3Rpb25FeHBsYW5hdGlvbn1cbiAgICovXG4gIGV4cGxhaW5UcmFuc2ZlclRyYW5zYWN0aW9uKGpzb246IFR4RGF0YSwgZXhwbGFuYXRpb25SZXN1bHQ6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24pOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uZXhwbGFuYXRpb25SZXN1bHQsXG4gICAgICBvdXRwdXRBbW91bnQ6IGpzb24uYWN0aW9uc1swXS50cmFuc2Zlcj8uZGVwb3NpdC50b1N0cmluZygpIHx8ICcnLFxuICAgICAgb3V0cHV0czogW1xuICAgICAgICB7XG4gICAgICAgICAgYWRkcmVzczoganNvbi5yZWNlaXZlcklkLFxuICAgICAgICAgIGFtb3VudDoganNvbi5hY3Rpb25zWzBdLnRyYW5zZmVyPy5kZXBvc2l0LnRvU3RyaW5nKCkgfHwgJycsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhIGNvbXBsZXRlIGV4cGxhbmF0aW9uIGZvciBhIHN0YWtpbmcgYWN0aXZhdGUgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtUeERhdGF9IGpzb24gVGhlIHRyYW5zYWN0aW9uIGRhdGEgaW4ganNvbiBmb3JtYXRcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufSBleHBsYW5hdGlvblJlc3VsdCBUaGUgdHJhbnNhY3Rpb24gZXhwbGFuYXRpb24gdG8gYmUgY29tcGxldGVkXG4gICAqIEByZXR1cm5zIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufVxuICAgKi9cbiAgZXhwbGFpblN0YWtpbmdBY3RpdmF0ZVRyYW5zYWN0aW9uKGpzb246IFR4RGF0YSwgZXhwbGFuYXRpb25SZXN1bHQ6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24pOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICByZXR1cm4ge1xuICAgICAgLi4uZXhwbGFuYXRpb25SZXN1bHQsXG4gICAgICBvdXRwdXRBbW91bnQ6IGpzb24uYWN0aW9uc1swXS5mdW5jdGlvbkNhbGw/LmRlcG9zaXQudG9TdHJpbmcoKSB8fCAnJyxcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IGpzb24ucmVjZWl2ZXJJZCxcbiAgICAgICAgICBhbW91bnQ6IGpzb24uYWN0aW9uc1swXS5mdW5jdGlvbkNhbGw/LmRlcG9zaXQudG9TdHJpbmcoKSB8fCAnJyxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGEgY29tcGxldGUgZXhwbGFuYXRpb24gZm9yIGEgc3Rha2luZyB3aXRoZHJhdyB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge1R4RGF0YX0ganNvbiBUaGUgdHJhbnNhY3Rpb24gZGF0YSBpbiBqc29uIGZvcm1hdFxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9uRXhwbGFuYXRpb259IGV4cGxhbmF0aW9uUmVzdWx0IFRoZSB0cmFuc2FjdGlvbiBleHBsYW5hdGlvbiB0byBiZSBjb21wbGV0ZWRcbiAgICogQHJldHVybnMge1RyYW5zYWN0aW9uRXhwbGFuYXRpb259XG4gICAqL1xuICBleHBsYWluU3Rha2luZ1dpdGhkcmF3VHJhbnNhY3Rpb24oanNvbjogVHhEYXRhLCBleHBsYW5hdGlvblJlc3VsdDogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbik6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24ge1xuICAgIGNvbnN0IGFtb3VudCA9IGpzb24uYWN0aW9uc1swXS5mdW5jdGlvbkNhbGw/LmFyZ3MuYW1vdW50IGFzIHN0cmluZztcbiAgICByZXR1cm4ge1xuICAgICAgLi4uZXhwbGFuYXRpb25SZXN1bHQsXG4gICAgICBvdXRwdXRBbW91bnQ6IGFtb3VudCxcbiAgICAgIG91dHB1dHM6IFtcbiAgICAgICAge1xuICAgICAgICAgIGFkZHJlc3M6IGpzb24uc2lnbmVySWQsXG4gICAgICAgICAgYW1vdW50OiBhbW91bnQsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgdG90YWwgZnVuZ2libGUgdG9rZW4gYW1vdW50ICYgdG90YWwgbmF0aXZlIG5lYXIgYW1vdW50XG4gICAqXG4gICAqIEBwYXJhbSB7QWN0aW9uW119IGFjdGlvbnMgdGhlIGxpc3Qgb2YgZGVsZWdhdGUgdHJhbnNhY3Rpb24gYWN0aW9uc1xuICAgKiBAcmV0dXJucyB7U3RyaW5nfSBlaXRoZXIgbmF0aXZlIG5lYXIgYW1vdW50IG9yIGZ1bmdpYmxlIHRva2VuIGFtb3VudFxuICAgKi9cbiAgY2FsY3VsYXRlVG90YWxPdXRwdXRBbW91bnQoYWN0aW9uczogQWN0aW9uW10pOiBzdHJpbmcge1xuICAgIGxldCBoYXNGdFRyYW5zZmVyID0gZmFsc2U7XG4gICAgbGV0IGhhc1N0b3JhZ2VEZXBvc2l0ID0gZmFsc2U7XG5cbiAgICBsZXQgdG90YWxUb2tlbkFtb3VudCA9IEJpZ0ludCgwKTtcbiAgICBsZXQgdG90YWxOZWFyRGVwb3NpdCA9IEJpZ0ludCgwKTtcblxuICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIGFjdGlvbnMpIHtcbiAgICAgIGlmIChhY3Rpb24uZnVuY3Rpb25DYWxsKSB7XG4gICAgICAgIGNvbnN0IGZ1bmN0aW9uQ2FsbCA9IGFjdGlvbi5mdW5jdGlvbkNhbGw7XG4gICAgICAgIGNvbnN0IG1ldGhvZE5hbWUgPSBmdW5jdGlvbkNhbGwubWV0aG9kTmFtZTtcbiAgICAgICAgY29uc3QgYXJncyA9IGZ1bmN0aW9uQ2FsbC5hcmdzO1xuICAgICAgICBjb25zdCBkZXBvc2l0ID0gQmlnSW50KGZ1bmN0aW9uQ2FsbC5kZXBvc2l0KTtcbiAgICAgICAgaWYgKG1ldGhvZE5hbWUgPT09IEZUX1RSQU5TRkVSKSB7XG4gICAgICAgICAgaGFzRnRUcmFuc2ZlciA9IHRydWU7XG4gICAgICAgICAgY29uc3QgYW1vdW50U3RyID0gYXJnc1snYW1vdW50J10gYXMgc3RyaW5nO1xuICAgICAgICAgIGlmIChhcmdzLmFtb3VudCkge1xuICAgICAgICAgICAgdG90YWxUb2tlbkFtb3VudCArPSBCaWdJbnQoYW1vdW50U3RyKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG1ldGhvZE5hbWUgPT09IFNUT1JBR0VfREVQT1NJVCkge1xuICAgICAgICAgIGhhc1N0b3JhZ2VEZXBvc2l0ID0gdHJ1ZTtcbiAgICAgICAgICB0b3RhbE5lYXJEZXBvc2l0ICs9IGRlcG9zaXQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGhhc0Z0VHJhbnNmZXIpIHtcbiAgICAgIHJldHVybiB0b3RhbFRva2VuQW1vdW50LnRvU3RyaW5nKCk7XG4gICAgfSBlbHNlIGlmIChoYXNTdG9yYWdlRGVwb3NpdCkge1xuICAgICAgcmV0dXJuIHRvdGFsTmVhckRlcG9zaXQudG9TdHJpbmcoKTtcbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBjb21wbGV0ZSBleHBsYW5hdGlvbiBmb3IgYSB0b2tlbiB0cmFuc2ZlciB0cmFuc2FjdGlvblxuICAgKiBAcGFyYW0ge1R4RGF0YX0ganNvbiBUaGUgdHJhbnNhY3Rpb24gZGF0YSBpbiBqc29uIGZvcm1hdFxuICAgKiBAcGFyYW0ge1RyYW5zYWN0aW9uRXhwbGFuYXRpb259IGV4cGxhbmF0aW9uUmVzdWx0IFRoZSB0cmFuc2FjdGlvbiBleHBsYW5hdGlvbiB0byBiZSBjb21wbGV0ZWRcbiAgICogQHJldHVybnMge1RyYW5zYWN0aW9uRXhwbGFuYXRpb259XG4gICAqL1xuICBleHBsYWluVG9rZW5UcmFuc2ZlclRyYW5zYWN0aW9uKGpzb246IFR4RGF0YSwgZXhwbGFuYXRpb25SZXN1bHQ6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24pOiBUcmFuc2FjdGlvbkV4cGxhbmF0aW9uIHtcbiAgICBjb25zdCBhY3Rpb25zID0ganNvbi5hY3Rpb25zO1xuICAgIGNvbnN0IG91dHB1dEFtb3VudCA9IHRoaXMuY2FsY3VsYXRlVG90YWxPdXRwdXRBbW91bnQoYWN0aW9ucyk7XG4gICAgY29uc3Qgb3V0cHV0czogSVRyYW5zYWN0aW9uUmVjaXBpZW50W10gPSBbXTtcbiAgICBhY3Rpb25zLm1hcCgoYWN0aW9uKSA9PiB7XG4gICAgICBpZiAoYWN0aW9uLmZ1bmN0aW9uQ2FsbCkge1xuICAgICAgICBjb25zdCBmdW5jdGlvbkNhbGwgPSBhY3Rpb24uZnVuY3Rpb25DYWxsO1xuICAgICAgICBpZiAoZnVuY3Rpb25DYWxsLm1ldGhvZE5hbWUgPT09IEZUX1RSQU5TRkVSKSB7XG4gICAgICAgICAgY29uc3QgYW1vdW50U3RyID0gZnVuY3Rpb25DYWxsLmFyZ3NbJ2Ftb3VudCddIGFzIHN0cmluZztcbiAgICAgICAgICBjb25zdCByZWNlaXZlcklkID0gZnVuY3Rpb25DYWxsLmFyZ3NbJ3JlY2VpdmVyX2lkJ10gYXMgc3RyaW5nO1xuICAgICAgICAgIC8vIGluIGZ0IHRyYW5zZmVyLCB0aGUgb3V0ZXIgcmVjZWl2ZXIgaWQgd2lsbCBiZSBjb250cmFjdCBhZGRyZXNzIG9mIHRoZSB0b2tlblxuICAgICAgICAgIGNvbnN0IHRva2VuTmFtZSA9IHV0aWxzLmZpbmRUb2tlbk5hbWVGcm9tQ29udHJhY3RBZGRyZXNzKGpzb24ucmVjZWl2ZXJJZCk7XG4gICAgICAgICAgY29uc3Qgb3V0cHV0OiBJVHJhbnNhY3Rpb25SZWNpcGllbnQgPSB7XG4gICAgICAgICAgICBhZGRyZXNzOiByZWNlaXZlcklkLFxuICAgICAgICAgICAgYW1vdW50OiBhbW91bnRTdHIsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBpZiAodG9rZW5OYW1lKSB7XG4gICAgICAgICAgICBvdXRwdXQudG9rZW5OYW1lID0gdG9rZW5OYW1lO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvdXRwdXRzLnB1c2gob3V0cHV0KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICAuLi5leHBsYW5hdGlvblJlc3VsdCxcbiAgICAgIG91dHB1dEFtb3VudDogb3V0cHV0QW1vdW50LFxuICAgICAgb3V0cHV0czogb3V0cHV0cyxcbiAgICB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBjb21wbGV0ZSBleHBsYW5hdGlvbiBmb3IgYSBzdG9yYWdlIGRlcG9zaXQgdHJhbnNhY3Rpb25cbiAgICogQHBhcmFtIHtUeERhdGF9IGpzb24gVGhlIHRyYW5zYWN0aW9uIGRhdGEgaW4ganNvbiBmb3JtYXRcbiAgICogQHBhcmFtIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufSBleHBsYW5hdGlvblJlc3VsdCBUaGUgdHJhbnNhY3Rpb24gZXhwbGFuYXRpb24gdG8gYmUgY29tcGxldGVkXG4gICAqIEByZXR1cm5zIHtUcmFuc2FjdGlvbkV4cGxhbmF0aW9ufVxuICAgKi9cbiAgZXhwbGFpblN0b3JhZ2VEZXBvc2l0VHJhbnNhY3Rpb24oanNvbjogVHhEYXRhLCBleHBsYW5hdGlvblJlc3VsdDogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbik6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24ge1xuICAgIGNvbnN0IGFjdGlvbnMgPSBqc29uLmFjdGlvbnM7XG4gICAgY29uc3Qgb3V0cHV0QW1vdW50ID0gdGhpcy5jYWxjdWxhdGVUb3RhbE91dHB1dEFtb3VudChhY3Rpb25zKTtcbiAgICBjb25zdCBvdXRwdXRzOiBJVHJhbnNhY3Rpb25SZWNpcGllbnRbXSA9IFtdO1xuICAgIGFjdGlvbnMubWFwKChhY3Rpb24pID0+IHtcbiAgICAgIGlmIChhY3Rpb24uZnVuY3Rpb25DYWxsKSB7XG4gICAgICAgIGNvbnN0IGZ1bmN0aW9uQ2FsbCA9IGFjdGlvbi5mdW5jdGlvbkNhbGw7XG4gICAgICAgIGlmIChmdW5jdGlvbkNhbGwubWV0aG9kTmFtZSA9PT0gU1RPUkFHRV9ERVBPU0lUKSB7XG4gICAgICAgICAgY29uc3QgcmVjZWl2ZXJJZCA9XG4gICAgICAgICAgICBmdW5jdGlvbkNhbGwuYXJncyAmJiBmdW5jdGlvbkNhbGwuYXJnc1snYWNjb3VudF9pZCddXG4gICAgICAgICAgICAgID8gKGZ1bmN0aW9uQ2FsbC5hcmdzWydhY2NvdW50X2lkJ10gYXMgc3RyaW5nKVxuICAgICAgICAgICAgICA6IGpzb24uc2lnbmVySWQ7XG4gICAgICAgICAgLy8gaW4gc3RvcmFnZSBkZXBvc2l0LCB0aGUgb3V0ZXIgcmVjZWl2ZXIgaWQgd2lsbCBiZSBjb250cmFjdCBhZGRyZXNzIG9mIHRoZSB0b2tlblxuICAgICAgICAgIGNvbnN0IHRva2VuTmFtZSA9IHV0aWxzLmZpbmRUb2tlbk5hbWVGcm9tQ29udHJhY3RBZGRyZXNzKGpzb24ucmVjZWl2ZXJJZCk7XG4gICAgICAgICAgY29uc3Qgb3V0cHV0OiBJVHJhbnNhY3Rpb25SZWNpcGllbnQgPSB7XG4gICAgICAgICAgICBhZGRyZXNzOiByZWNlaXZlcklkLFxuICAgICAgICAgICAgYW1vdW50OiBmdW5jdGlvbkNhbGwuZGVwb3NpdCxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGlmICh0b2tlbk5hbWUpIHtcbiAgICAgICAgICAgIG91dHB1dC50b2tlbk5hbWUgPSB0b2tlbk5hbWU7XG4gICAgICAgICAgfVxuICAgICAgICAgIG91dHB1dHMucHVzaChvdXRwdXQpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmV4cGxhbmF0aW9uUmVzdWx0LFxuICAgICAgb3V0cHV0QW1vdW50OiBvdXRwdXRBbW91bnQsXG4gICAgICBvdXRwdXRzOiBvdXRwdXRzLFxuICAgIH07XG4gIH1cblxuICAvKiogQGluaGVyaXRkb2MgKi9cbiAgZXhwbGFpblRyYW5zYWN0aW9uKCk6IFRyYW5zYWN0aW9uRXhwbGFuYXRpb24ge1xuICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMudG9Kc29uKCk7XG4gICAgY29uc3QgZGlzcGxheU9yZGVyID0gWydvdXRwdXRBbW91bnQnLCAnY2hhbmdlQW1vdW50JywgJ291dHB1dHMnLCAnY2hhbmdlT3V0cHV0cycsICdmZWUnLCAndHlwZSddO1xuICAgIGNvbnN0IG91dHB1dHM6IFRyYW5zYWN0aW9uUmVjaXBpZW50W10gPSBbXTtcbiAgICBjb25zdCBleHBsYW5hdGlvblJlc3VsdDogVHJhbnNhY3Rpb25FeHBsYW5hdGlvbiA9IHtcbiAgICAgIC8vIHR4aGFzaCB1c2VkIHRvIGlkZW50aWZ5IHRoZSB0cmFuc2FjdGlvbnNcbiAgICAgIGlkOiByZXN1bHQuaWQgfHwgJycsXG4gICAgICBkaXNwbGF5T3JkZXIsXG4gICAgICBvdXRwdXRBbW91bnQ6ICcwJyxcbiAgICAgIGNoYW5nZUFtb3VudDogJzAnLFxuICAgICAgY2hhbmdlT3V0cHV0czogW10sXG4gICAgICBvdXRwdXRzLFxuICAgICAgZmVlOiB7IGZlZTogJycgfSxcbiAgICAgIHR5cGU6IHRoaXMudHlwZSxcbiAgICB9O1xuICAgIHN3aXRjaCAodGhpcy50eXBlKSB7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TZW5kOlxuICAgICAgICBpZiAocmVzdWx0LmFjdGlvbnMubGVuZ3RoID4gMSB8fCByZXN1bHQuYWN0aW9uc1swXS5mdW5jdGlvbkNhbGwpIHtcbiAgICAgICAgICByZXR1cm4gdGhpcy5leHBsYWluVG9rZW5UcmFuc2ZlclRyYW5zYWN0aW9uKHJlc3VsdCwgZXhwbGFuYXRpb25SZXN1bHQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmV4cGxhaW5UcmFuc2ZlclRyYW5zYWN0aW9uKHJlc3VsdCwgZXhwbGFuYXRpb25SZXN1bHQpO1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ0FjdGl2YXRlOlxuICAgICAgICByZXR1cm4gdGhpcy5leHBsYWluU3Rha2luZ0FjdGl2YXRlVHJhbnNhY3Rpb24ocmVzdWx0LCBleHBsYW5hdGlvblJlc3VsdCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdGFraW5nRGVhY3RpdmF0ZTpcbiAgICAgICAgcmV0dXJuIGV4cGxhbmF0aW9uUmVzdWx0O1xuICAgICAgY2FzZSBUcmFuc2FjdGlvblR5cGUuU3Rha2luZ1dpdGhkcmF3OlxuICAgICAgICByZXR1cm4gdGhpcy5leHBsYWluU3Rha2luZ1dpdGhkcmF3VHJhbnNhY3Rpb24ocmVzdWx0LCBleHBsYW5hdGlvblJlc3VsdCk7XG4gICAgICBjYXNlIFRyYW5zYWN0aW9uVHlwZS5TdG9yYWdlRGVwb3NpdDpcbiAgICAgICAgcmV0dXJuIHRoaXMuZXhwbGFpblN0b3JhZ2VEZXBvc2l0VHJhbnNhY3Rpb24ocmVzdWx0LCBleHBsYW5hdGlvblJlc3VsdCk7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgSW52YWxpZFRyYW5zYWN0aW9uRXJyb3IoJ1RyYW5zYWN0aW9uIHR5cGUgbm90IHN1cHBvcnRlZCcpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0VHJhbnNhY3Rpb25IYXNoKCk6IFVpbnQ4QXJyYXkge1xuICAgIGNvbnN0IHNlcmlhbGl6ZWRUeCA9IG5lYXJBUEkudXRpbHMuc2VyaWFsaXplLnNlcmlhbGl6ZShcbiAgICAgIG5lYXJBUEkudHJhbnNhY3Rpb25zLlNDSEVNQS5UcmFuc2FjdGlvbixcbiAgICAgIHRoaXMuX25lYXJUcmFuc2FjdGlvblxuICAgICk7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KHNoYTI1Ni5hcnJheShzZXJpYWxpemVkVHgpKTtcbiAgfVxuXG4gIGdldCBzaWduYWJsZVBheWxvYWQoKTogQnVmZmVyIHtcbiAgICBpZiAoIXRoaXMuX25lYXJUcmFuc2FjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEludmFsaWRUcmFuc2FjdGlvbkVycm9yKCdlbXB0eSB0cmFuc2FjdGlvbicpO1xuICAgIH1cbiAgICByZXR1cm4gQnVmZmVyLmZyb20odGhpcy5nZXRUcmFuc2FjdGlvbkhhc2goKSk7XG4gIH1cblxuICAvKipcbiAgICogQ29uc3RydWN0cyBhIHNpZ25lZCBwYXlsb2FkIHVzaW5nIGNvbnN0cnVjdC5zaWduVHhcbiAgICogVGhpcyBtZXRob2Qgd2lsbCBiZSBjYWxsZWQgZHVyaW5nIHRoZSBidWlsZCBzdGVwIGlmIGEgVFNTIHNpZ25hdHVyZVxuICAgKiBpcyBhZGRlZCBhbmQgd2lsbCBzZXQgdGhlIHNpZ25UcmFuc2FjdGlvbiB3aGljaCBpcyB0aGUgdHhIZXggdGhhdCB3aWxsIGJlIGJyb2FkY2FzdGVkXG4gICAqIEFzIHdlbGwgYXMgYWRkIHRoZSBzaWduYXR1cmUgdXNlZCB0byBzaWduIHRvIHRoZSBzaWduYXR1cmUgYXJyYXkgaW4gaGV4IGZvcm1hdFxuICAgKlxuICAgKiBAcGFyYW0ge0J1ZmZlcn0gc2lnbmF0dXJlIFRoZSBzaWduYXR1cmUgdG8gYmUgYWRkZWQgdG8gYSBuZWFyIHRyYW5zYWN0aW9uXG4gICAqL1xuICBjb25zdHJ1Y3RTaWduZWRQYXlsb2FkKHNpZ25hdHVyZTogQnVmZmVyKTogdm9pZCB7XG4gICAgdGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uID0gbmV3IG5lYXJBUEkudHJhbnNhY3Rpb25zLlNpZ25lZFRyYW5zYWN0aW9uKHtcbiAgICAgIHRyYW5zYWN0aW9uOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24sXG4gICAgICBzaWduYXR1cmU6IG5ldyBuZWFyQVBJLnRyYW5zYWN0aW9ucy5TaWduYXR1cmUoe1xuICAgICAgICBrZXlUeXBlOiB0aGlzLl9uZWFyVHJhbnNhY3Rpb24ucHVibGljS2V5LmtleVR5cGUsXG4gICAgICAgIGRhdGE6IHNpZ25hdHVyZSxcbiAgICAgIH0pLFxuICAgIH0pO1xuICAgIHRoaXMubG9hZElucHV0c0FuZE91dHB1dHMoKTtcbiAgfVxuICAvKiogQGluaGVyaXRkb2MgKiovXG4gIGdldCBzaWduYXR1cmUoKTogc3RyaW5nW10ge1xuICAgIGNvbnN0IHNpZ25hdHVyZXM6IHN0cmluZ1tdID0gW107XG5cbiAgICBpZiAodGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uICYmIHRoaXMuX25lYXJTaWduZWRUcmFuc2FjdGlvbi5zaWduYXR1cmUuZWQyNTUxOVNpZ25hdHVyZSkge1xuICAgICAgc2lnbmF0dXJlcy5wdXNoKGJhc2U1OC5lbmNvZGUodGhpcy5fbmVhclNpZ25lZFRyYW5zYWN0aW9uLnNpZ25hdHVyZS5lZDI1NTE5U2lnbmF0dXJlLmRhdGEpKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2lnbmF0dXJlcztcbiAgfVxufVxuIl19Выполнить команду
Для локальной разработки. Не используйте в интернете!