UNPKG

@c4tplatform/caminojs

Version:
484 lines 65.8 kB
"use strict"; /** * @packageDocumentation * @module Common-Output */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseNFTOutput = exports.StandardAmountOutput = exports.StandardTransferableOutput = exports.StandardParseableOutput = exports.Output = exports.OutputOwners = exports.Address = exports.BaseOutputComparator = void 0; const buffer_1 = require("buffer/"); const bn_js_1 = __importDefault(require("bn.js")); const bintools_1 = __importDefault(require("../utils/bintools")); const nbytes_1 = require("./nbytes"); const helperfunctions_1 = require("../utils/helperfunctions"); const serialization_1 = require("../utils/serialization"); const errors_1 = require("../utils/errors"); /** * @ignore */ const bintools = bintools_1.default.getInstance(); const serialization = serialization_1.Serialization.getInstance(); const BaseOutputComparator = () => (a, b) => { const aoutid = buffer_1.Buffer.alloc(4); aoutid.writeUInt32BE(a.getOutputID(), 0); const abuff = a.toBuffer(); const boutid = buffer_1.Buffer.alloc(4); boutid.writeUInt32BE(b.getOutputID(), 0); const bbuff = b.toBuffer(); const asort = buffer_1.Buffer.concat([aoutid, abuff], aoutid.length + abuff.length); const bsort = buffer_1.Buffer.concat([boutid, bbuff], boutid.length + bbuff.length); return buffer_1.Buffer.compare(asort, bsort); }; exports.BaseOutputComparator = BaseOutputComparator; /** * Class for representing an address used in [[Output]] types */ class Address extends nbytes_1.NBytes { /** * Returns a base-58 representation of the [[Address]]. */ toString() { return bintools.cb58Encode(this.toBuffer()); } /** * Takes a base-58 string containing an [[Address]], parses it, populates the class, and returns the length of the Address in bytes. * * @param bytes A base-58 string containing a raw [[Address]] * * @returns The length of the raw [[Address]] */ fromString(addr) { const addrbuff = bintools.b58ToBuffer(addr); if (addrbuff.length === 24 && bintools.validateChecksum(addrbuff)) { const newbuff = bintools.copyFrom(addrbuff, 0, addrbuff.length - 4); if (newbuff.length === 20) { this.bytes = newbuff; } } else if (addrbuff.length === 24) { throw new errors_1.ChecksumError("Error - Address.fromString: invalid checksum on address"); } else if (addrbuff.length === 20) { this.bytes = addrbuff; } else { /* istanbul ignore next */ throw new errors_1.AddressError("Error - Address.fromString: invalid address"); } return this.getSize(); } clone() { let newbase = new Address(); newbase.fromBuffer(this.toBuffer()); return newbase; } create() { return new Address(); } /** * Class for representing an address used in [[Output]] types */ constructor() { super(); this._typeName = "Address"; this._typeID = undefined; //serialize and deserialize both are inherited this.bytes = buffer_1.Buffer.alloc(20); this.bsize = 20; } } exports.Address = Address; /** * Returns a function used to sort an array of [[Address]]es */ Address.comparator = () => (a, b) => buffer_1.Buffer.compare(a.toBuffer(), b.toBuffer()); /** * Defines the most basic values for output ownership. Mostly inherited from, but can be used in population of NFT Owner data. */ class OutputOwners extends serialization_1.Serializable { serialize(encoding = "hex") { let fields = super.serialize(encoding); return Object.assign(Object.assign({}, fields), { locktime: serialization.encoder(this.locktime, encoding, "Buffer", "decimalString", 8), threshold: serialization.encoder(this.threshold, encoding, "Buffer", "decimalString", 4), addresses: this.addresses.map((a) => a.serialize(encoding)) }); } deserialize(fields, encoding = "hex") { super.deserialize(fields, encoding); this.locktime = serialization.decoder(fields["locktime"], encoding, "decimalString", "Buffer", 8); this.threshold = serialization.decoder(fields["threshold"], encoding, "decimalString", "Buffer", 4); this.addresses = fields["addresses"].map((a) => { let addr = new Address(); addr.deserialize(a, encoding); return addr; }); this.numaddrs = buffer_1.Buffer.alloc(4); this.numaddrs.writeUInt32BE(this.addresses.length, 0); } /** * Returns a base-58 string representing the [[Output]]. */ fromBuffer(bytes, offset = 0) { this.locktime = bintools.copyFrom(bytes, offset, offset + 8); offset += 8; this.threshold = bintools.copyFrom(bytes, offset, offset + 4); offset += 4; this.numaddrs = bintools.copyFrom(bytes, offset, offset + 4); offset += 4; const numaddrs = this.numaddrs.readUInt32BE(0); this.addresses = []; for (let i = 0; i < numaddrs; i++) { const addr = new Address(); offset = addr.fromBuffer(bytes, offset); this.addresses.push(addr); } this.addresses.sort(Address.comparator()); return offset; } /** * Returns the buffer representing the [[Output]] instance. */ toBuffer() { this.addresses.sort(Address.comparator()); this.numaddrs.writeUInt32BE(this.addresses.length, 0); let bsize = this.locktime.length + this.threshold.length + this.numaddrs.length; const barr = [this.locktime, this.threshold, this.numaddrs]; for (let i = 0; i < this.addresses.length; i++) { const b = this.addresses[`${i}`].toBuffer(); barr.push(b); bsize += b.length; } return buffer_1.Buffer.concat(barr, bsize); } /** * Returns a base-58 string representing the [[Output]]. */ toString() { return bintools.bufferToB58(this.toBuffer()); } /** * An [[Output]] class which contains addresses, locktimes, and thresholds. * * @param addresses An array of {@link https://github.com/feross/buffer|Buffer}s representing output owner's addresses * @param locktime A {@link https://github.com/indutny/bn.js/|BN} representing the locktime * @param threshold A number representing the threshold number of signers required to sign the transaction */ constructor(addresses = undefined, locktime = undefined, threshold = undefined) { super(); this._typeName = "OutputOwners"; this._typeID = undefined; this.locktime = buffer_1.Buffer.alloc(8); this.threshold = buffer_1.Buffer.alloc(4); this.numaddrs = buffer_1.Buffer.alloc(4); this.addresses = []; /** * Returns the threshold of signers required to spend this output. */ this.getThreshold = () => this.threshold.readUInt32BE(0); /** * Returns the a {@link https://github.com/indutny/bn.js/|BN} repersenting the UNIX Timestamp when the lock is made available. */ this.getLocktime = () => bintools.fromBufferToBN(this.locktime); /** * Returns an array of {@link https://github.com/feross/buffer|Buffer}s for the addresses. */ this.getAddresses = () => { const result = []; for (let i = 0; i < this.addresses.length; i++) { result.push(this.addresses[`${i}`].toBuffer()); } return result; }; /** * Returns an the length of the Addresses array. */ this.getAddressesLength = () => this.addresses.length; /** * Returns the index of the address. * * @param address A {@link https://github.com/feross/buffer|Buffer} of the address to look up to return its index. * * @returns The index of the address. */ this.getAddressIdx = (address) => { for (let i = 0; i < this.addresses.length; i++) { if (this.addresses[`${i}`].toBuffer().toString("hex") === address.toString("hex")) { return i; } } /* istanbul ignore next */ return -1; }; /** * Returns the address from the index provided. * * @param idx The index of the address. * * @returns Returns the string representing the address. */ this.getAddress = (idx) => { if (idx < this.addresses.length) { return this.addresses[`${idx}`].toBuffer(); } throw new errors_1.AddressIndexError("Error - Output.getAddress: idx out of range"); }; /** * Given an array of address {@link https://github.com/feross/buffer|Buffer}s and an optional timestamp, returns true if the addresses meet the threshold required to spend the output. */ this.meetsThreshold = (addresses, asOf = undefined) => { let now; if (typeof asOf === "undefined") { now = (0, helperfunctions_1.UnixNow)(); } else { now = asOf; } const qualified = this.getSpenders(addresses, now); const threshold = this.threshold.readUInt32BE(0); if (qualified.length >= threshold) { return true; } return false; }; /** * Given an array of addresses and an optional timestamp, select an array of address {@link https://github.com/feross/buffer|Buffer}s of qualified spenders for the output. */ this.getSpenders = (addresses, asOf = undefined) => { const qualified = []; let now; if (typeof asOf === "undefined") { now = (0, helperfunctions_1.UnixNow)(); } else { now = asOf; } const locktime = bintools.fromBufferToBN(this.locktime); if (now.lte(locktime)) { // not unlocked, not spendable return qualified; } const threshold = this.threshold.readUInt32BE(0); for (let i = 0; i < this.addresses.length && qualified.length < threshold; i++) { for (let j = 0; j < addresses.length && qualified.length < threshold; j++) { if (addresses[`${j}`].toString("hex") === this.addresses[`${i}`].toBuffer().toString("hex")) { qualified.push(addresses[`${j}`]); } } } return qualified; }; if (typeof addresses !== "undefined" && addresses.length) { const addrs = []; for (let i = 0; i < addresses.length; i++) { addrs[`${i}`] = new Address(); addrs[`${i}`].fromBuffer(addresses[`${i}`]); } this.addresses = addrs; this.addresses.sort(Address.comparator()); this.numaddrs.writeUInt32BE(this.addresses.length, 0); } if (typeof threshold !== undefined) { this.threshold.writeUInt32BE(threshold || 1, 0); } if (typeof locktime !== "undefined") { this.locktime = bintools.fromBNToBuffer(locktime, 8); } } static fromArray(b) { let offset = 6; //version + counter let num = b.readUInt32BE(2); const result = []; while (offset < b.length && num-- > 0) { const t = new OutputOwners(); offset = t.fromBuffer(b, offset); result.push(t); } return result; } static toArray(o) { const numOutputOwners = buffer_1.Buffer.alloc(6); numOutputOwners.writeUInt32BE(o.length, 2); let bsize = 6; const barr = [numOutputOwners]; for (const outputOwner of o) { const b = outputOwner.toBuffer(); bsize += b.length; barr.push(b); } return buffer_1.Buffer.concat(barr, bsize); } } exports.OutputOwners = OutputOwners; class Output extends OutputOwners { constructor() { super(...arguments); this._typeName = "Output"; this._typeID = undefined; } } exports.Output = Output; class StandardParseableOutput extends serialization_1.Serializable { serialize(encoding = "hex") { let fields = super.serialize(encoding); return Object.assign(Object.assign({}, fields), { output: this.output.serialize(encoding) }); } toBuffer() { const outbuff = this.output.toBuffer(); const outid = buffer_1.Buffer.alloc(4); outid.writeUInt32BE(this.output.getOutputID(), 0); const barr = [outid, outbuff]; return buffer_1.Buffer.concat(barr, outid.length + outbuff.length); } getThreshold() { return this.output.getThreshold(); } getLocktime() { return this.output.getLocktime(); } getAddresses() { return this.output.getAddresses(); } meetsThreshold(addrs, asOf) { return this.output.meetsThreshold(addrs, asOf); } /** * Class representing an [[ParseableOutput]] for a transaction. * * @param output A number representing the InputID of the [[ParseableOutput]] */ constructor(output = undefined) { super(); this._typeName = "StandardParseableOutput"; this._typeID = undefined; this.getOutput = () => this.output; this.output = output; } } exports.StandardParseableOutput = StandardParseableOutput; /** * Returns a function used to sort an array of [[ParseableOutput]]s */ StandardParseableOutput.comparator = () => (a, b) => { const sorta = a.toBuffer(); const sortb = b.toBuffer(); return buffer_1.Buffer.compare(sorta, sortb); }; class StandardTransferableOutput extends StandardParseableOutput { serialize(encoding = "hex") { let fields = super.serialize(encoding); return Object.assign(Object.assign({}, fields), { assetID: serialization.encoder(this.assetID, encoding, "Buffer", "cb58") }); } deserialize(fields, encoding = "hex") { super.deserialize(fields, encoding); this.assetID = serialization.decoder(fields["assetID"], encoding, "cb58", "Buffer", 32); } toBuffer() { const parseableBuff = super.toBuffer(); const barr = [this.assetID, parseableBuff]; return buffer_1.Buffer.concat(barr, this.assetID.length + parseableBuff.length); } /** * Class representing an [[StandardTransferableOutput]] for a transaction. * * @param assetID A {@link https://github.com/feross/buffer|Buffer} representing the assetID of the [[Output]] * @param output A number representing the InputID of the [[StandardTransferableOutput]] */ constructor(assetID = undefined, output = undefined) { super(output); this._typeName = "StandardTransferableOutput"; this._typeID = undefined; this.assetID = undefined; this.getAssetID = () => this.assetID; if (typeof assetID !== "undefined") { this.assetID = assetID; } } } exports.StandardTransferableOutput = StandardTransferableOutput; /** * An [[Output]] class which specifies a token amount . */ class StandardAmountOutput extends Output { serialize(encoding = "hex") { let fields = super.serialize(encoding); return Object.assign(Object.assign({}, fields), { amount: serialization.encoder(this.amount, encoding, "Buffer", "decimalString", 8) }); } deserialize(fields, encoding = "hex") { super.deserialize(fields, encoding); this.amount = serialization.decoder(fields["amount"], encoding, "decimalString", "Buffer", 8); this.amountValue = bintools.fromBufferToBN(this.amount); } /** * Returns the amount as a {@link https://github.com/indutny/bn.js/|BN}. */ getAmount() { return this.amountValue.clone(); } /** * Popuates the instance from a {@link https://github.com/feross/buffer|Buffer} representing the [[StandardAmountOutput]] and returns the size of the output. */ fromBuffer(outbuff, offset = 0) { this.amount = bintools.copyFrom(outbuff, offset, offset + 8); this.amountValue = bintools.fromBufferToBN(this.amount); offset += 8; return super.fromBuffer(outbuff, offset); } /** * Returns the buffer representing the [[StandardAmountOutput]] instance. */ toBuffer() { const superbuff = super.toBuffer(); const bsize = this.amount.length + superbuff.length; this.numaddrs.writeUInt32BE(this.addresses.length, 0); const barr = [this.amount, superbuff]; return buffer_1.Buffer.concat(barr, bsize); } /** * A [[StandardAmountOutput]] class which issues a payment on an assetID. * * @param amount A {@link https://github.com/indutny/bn.js/|BN} representing the amount in the output * @param addresses An array of {@link https://github.com/feross/buffer|Buffer}s representing addresses * @param locktime A {@link https://github.com/indutny/bn.js/|BN} representing the locktime * @param threshold A number representing the the threshold number of signers required to sign the transaction */ constructor(amount = undefined, addresses = undefined, locktime = undefined, threshold = undefined) { super(addresses, locktime, threshold); this._typeName = "StandardAmountOutput"; this._typeID = undefined; this.amount = buffer_1.Buffer.alloc(8); this.amountValue = new bn_js_1.default(0); if (typeof amount !== "undefined") { this.amountValue = amount.clone(); this.amount = bintools.fromBNToBuffer(amount, 8); } } } exports.StandardAmountOutput = StandardAmountOutput; /** * An [[Output]] class which specifies an NFT. */ class BaseNFTOutput extends Output { constructor() { super(...arguments); this._typeName = "BaseNFTOutput"; this._typeID = undefined; this.groupID = buffer_1.Buffer.alloc(4); /** * Returns the groupID as a number. */ this.getGroupID = () => { return this.groupID.readUInt32BE(0); }; } serialize(encoding = "hex") { let fields = super.serialize(encoding); return Object.assign(Object.assign({}, fields), { groupID: serialization.encoder(this.groupID, encoding, "Buffer", "decimalString", 4) }); } deserialize(fields, encoding = "hex") { super.deserialize(fields, encoding); this.groupID = serialization.decoder(fields["groupID"], encoding, "decimalString", "Buffer", 4); } } exports.BaseNFTOutput = BaseNFTOutput; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0cHV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbW1vbi9vdXRwdXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7R0FHRzs7Ozs7O0FBRUgsb0NBQWdDO0FBQ2hDLGtEQUFzQjtBQUN0QixpRUFBd0M7QUFDeEMscUNBQWlDO0FBQ2pDLDhEQUFrRDtBQUNsRCwwREFJK0I7QUFDL0IsNENBQWdGO0FBRWhGOztHQUVHO0FBQ0gsTUFBTSxRQUFRLEdBQWEsa0JBQVEsQ0FBQyxXQUFXLEVBQUUsQ0FBQTtBQUNqRCxNQUFNLGFBQWEsR0FBa0IsNkJBQWEsQ0FBQyxXQUFXLEVBQUUsQ0FBQTtBQW9CekQsTUFBTSxvQkFBb0IsR0FDL0IsR0FBbUQsRUFBRSxDQUNyRCxDQUFDLENBQWEsRUFBRSxDQUFhLEVBQWMsRUFBRTtJQUMzQyxNQUFNLE1BQU0sR0FBVyxlQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3RDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3hDLE1BQU0sS0FBSyxHQUFXLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtJQUVsQyxNQUFNLE1BQU0sR0FBVyxlQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQ3RDLE1BQU0sQ0FBQyxhQUFhLENBQUMsQ0FBQyxDQUFDLFdBQVcsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ3hDLE1BQU0sS0FBSyxHQUFXLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtJQUVsQyxNQUFNLEtBQUssR0FBVyxlQUFNLENBQUMsTUFBTSxDQUNqQyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsRUFDZixNQUFNLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQzdCLENBQUE7SUFDRCxNQUFNLEtBQUssR0FBVyxlQUFNLENBQUMsTUFBTSxDQUNqQyxDQUFDLE1BQU0sRUFBRSxLQUFLLENBQUMsRUFDZixNQUFNLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQzdCLENBQUE7SUFDRCxPQUFPLGVBQU0sQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBZSxDQUFBO0FBQ25ELENBQUMsQ0FBQTtBQXBCVSxRQUFBLG9CQUFvQix3QkFvQjlCO0FBRUg7O0dBRUc7QUFDSCxNQUFhLE9BQVEsU0FBUSxlQUFNO0lBaUJqQzs7T0FFRztJQUNILFFBQVE7UUFDTixPQUFPLFFBQVEsQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUE7SUFDN0MsQ0FBQztJQUVEOzs7Ozs7T0FNRztJQUNILFVBQVUsQ0FBQyxJQUFZO1FBQ3JCLE1BQU0sUUFBUSxHQUFXLFFBQVEsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDbkQsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEVBQUUsSUFBSSxRQUFRLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDakUsTUFBTSxPQUFPLEdBQVcsUUFBUSxDQUFDLFFBQVEsQ0FDdkMsUUFBUSxFQUNSLENBQUMsRUFDRCxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FDcEIsQ0FBQTtZQUNELElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxFQUFFLEVBQUU7Z0JBQ3pCLElBQUksQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFBO2FBQ3JCO1NBQ0Y7YUFBTSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssRUFBRSxFQUFFO1lBQ2pDLE1BQU0sSUFBSSxzQkFBYSxDQUNyQix5REFBeUQsQ0FDMUQsQ0FBQTtTQUNGO2FBQU0sSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLEVBQUUsRUFBRTtZQUNqQyxJQUFJLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQTtTQUN0QjthQUFNO1lBQ0wsMEJBQTBCO1lBQzFCLE1BQU0sSUFBSSxxQkFBWSxDQUFDLDZDQUE2QyxDQUFDLENBQUE7U0FDdEU7UUFDRCxPQUFPLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQTtJQUN2QixDQUFDO0lBRUQsS0FBSztRQUNILElBQUksT0FBTyxHQUFZLElBQUksT0FBTyxFQUFFLENBQUE7UUFDcEMsT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtRQUNuQyxPQUFPLE9BQWUsQ0FBQTtJQUN4QixDQUFDO0lBRUQsTUFBTTtRQUNKLE9BQU8sSUFBSSxPQUFPLEVBQVUsQ0FBQTtJQUM5QixDQUFDO0lBRUQ7O09BRUc7SUFDSDtRQUNFLEtBQUssRUFBRSxDQUFBO1FBcEVDLGNBQVMsR0FBRyxTQUFTLENBQUE7UUFDckIsWUFBTyxHQUFHLFNBQVMsQ0FBQTtRQUU3Qiw4Q0FBOEM7UUFFcEMsVUFBSyxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUE7UUFDeEIsVUFBSyxHQUFHLEVBQUUsQ0FBQTtJQStEcEIsQ0FBQzs7QUF0RUgsMEJBdUVDO0FBOURDOztHQUVHO0FBQ0ksa0JBQVUsR0FDZixHQUE2QyxFQUFFLENBQy9DLENBQUMsQ0FBVSxFQUFFLENBQVUsRUFBYyxFQUFFLENBQ3JDLGVBQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBZSxDQUFBO0FBMEQ5RDs7R0FFRztBQUNILE1BQWEsWUFBYSxTQUFRLDRCQUFZO0lBSTVDLFNBQVMsQ0FBQyxXQUErQixLQUFLO1FBQzVDLElBQUksTUFBTSxHQUFXLEtBQUssQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDOUMsdUNBQ0ssTUFBTSxLQUNULFFBQVEsRUFBRSxhQUFhLENBQUMsT0FBTyxDQUM3QixJQUFJLENBQUMsUUFBUSxFQUNiLFFBQVEsRUFDUixRQUFRLEVBQ1IsZUFBZSxFQUNmLENBQUMsQ0FDRixFQUNELFNBQVMsRUFBRSxhQUFhLENBQUMsT0FBTyxDQUM5QixJQUFJLENBQUMsU0FBUyxFQUNkLFFBQVEsRUFDUixRQUFRLEVBQ1IsZUFBZSxFQUNmLENBQUMsQ0FDRixFQUNELFNBQVMsRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQVUsRUFBVSxFQUFFLENBQ25ELENBQUMsQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQ3RCLElBQ0Y7SUFDSCxDQUFDO0lBQ0QsV0FBVyxDQUFDLE1BQWMsRUFBRSxXQUErQixLQUFLO1FBQzlELEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFBO1FBQ25DLElBQUksQ0FBQyxRQUFRLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FDbkMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxFQUNsQixRQUFRLEVBQ1IsZUFBZSxFQUNmLFFBQVEsRUFDUixDQUFDLENBQ0YsQ0FBQTtRQUNELElBQUksQ0FBQyxTQUFTLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FDcEMsTUFBTSxDQUFDLFdBQVcsQ0FBQyxFQUNuQixRQUFRLEVBQ1IsZUFBZSxFQUNmLFFBQVEsRUFDUixDQUFDLENBQ0YsQ0FBQTtRQUNELElBQUksQ0FBQyxTQUFTLEdBQUcsTUFBTSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQVMsRUFBRSxFQUFFO1lBQ3JELElBQUksSUFBSSxHQUFZLElBQUksT0FBTyxFQUFFLENBQUE7WUFDakMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEVBQUUsUUFBUSxDQUFDLENBQUE7WUFDN0IsT0FBTyxJQUFJLENBQUE7UUFDYixDQUFDLENBQUMsQ0FBQTtRQUNGLElBQUksQ0FBQyxRQUFRLEdBQUcsZUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUMvQixJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQTtJQUN2RCxDQUFDO0lBOEhEOztPQUVHO0lBQ0gsVUFBVSxDQUFDLEtBQWEsRUFBRSxTQUFpQixDQUFDO1FBQzFDLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUM1RCxNQUFNLElBQUksQ0FBQyxDQUFBO1FBQ1gsSUFBSSxDQUFDLFNBQVMsR0FBRyxRQUFRLENBQUMsUUFBUSxDQUFDLEtBQUssRUFBRSxNQUFNLEVBQUUsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFBO1FBQzdELE1BQU0sSUFBSSxDQUFDLENBQUE7UUFDWCxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUE7UUFDNUQsTUFBTSxJQUFJLENBQUMsQ0FBQTtRQUNYLE1BQU0sUUFBUSxHQUFXLElBQUksQ0FBQyxRQUFRLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3RELElBQUksQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFBO1FBQ25CLEtBQUssSUFBSSxDQUFDLEdBQVcsQ0FBQyxFQUFFLENBQUMsR0FBRyxRQUFRLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDekMsTUFBTSxJQUFJLEdBQVksSUFBSSxPQUFPLEVBQUUsQ0FBQTtZQUNuQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxLQUFLLEVBQUUsTUFBTSxDQUFDLENBQUE7WUFDdkMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7U0FDMUI7UUFDRCxJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQTtRQUN6QyxPQUFPLE1BQU0sQ0FBQTtJQUNmLENBQUM7SUFFRDs7T0FFRztJQUNILFFBQVE7UUFDTixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQTtRQUN6QyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUNyRCxJQUFJLEtBQUssR0FDUCxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQTtRQUNyRSxNQUFNLElBQUksR0FBYSxDQUFDLElBQUksQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLFNBQVMsRUFBRSxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDckUsS0FBSyxJQUFJLENBQUMsR0FBVyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3RELE1BQU0sQ0FBQyxHQUFXLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFBO1lBQ25ELElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDWixLQUFLLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQTtTQUNsQjtRQUNELE9BQU8sZUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFDbkMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsUUFBUTtRQUNOLE9BQU8sUUFBUSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtJQUM5QyxDQUFDO0lBRUQ7Ozs7OztPQU1HO0lBQ0gsWUFDRSxZQUFzQixTQUFTLEVBQy9CLFdBQWUsU0FBUyxFQUN4QixZQUFvQixTQUFTO1FBRTdCLEtBQUssRUFBRSxDQUFBO1FBeE9DLGNBQVMsR0FBRyxjQUFjLENBQUE7UUFDMUIsWUFBTyxHQUFHLFNBQVMsQ0FBQTtRQWtEbkIsYUFBUSxHQUFXLGVBQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDbEMsY0FBUyxHQUFXLGVBQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDbkMsYUFBUSxHQUFXLGVBQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDbEMsY0FBUyxHQUFjLEVBQUUsQ0FBQTtRQUVuQzs7V0FFRztRQUNILGlCQUFZLEdBQUcsR0FBVyxFQUFFLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFFM0Q7O1dBRUc7UUFDSCxnQkFBVyxHQUFHLEdBQU8sRUFBRSxDQUFDLFFBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBRTlEOztXQUVHO1FBQ0gsaUJBQVksR0FBRyxHQUFhLEVBQUU7WUFDNUIsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFBO1lBQzNCLEtBQUssSUFBSSxDQUFDLEdBQVcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRTtnQkFDdEQsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFBO2FBQy9DO1lBQ0QsT0FBTyxNQUFNLENBQUE7UUFDZixDQUFDLENBQUE7UUFFRDs7V0FFRztRQUNILHVCQUFrQixHQUFHLEdBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFBO1FBRXhEOzs7Ozs7V0FNRztRQUNILGtCQUFhLEdBQUcsQ0FBQyxPQUFlLEVBQVUsRUFBRTtZQUMxQyxLQUFLLElBQUksQ0FBQyxHQUFXLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ3RELElBQ0UsSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztvQkFDakQsT0FBTyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFDdkI7b0JBQ0EsT0FBTyxDQUFDLENBQUE7aUJBQ1Q7YUFDRjtZQUNELDBCQUEwQjtZQUMxQixPQUFPLENBQUMsQ0FBQyxDQUFBO1FBQ1gsQ0FBQyxDQUFBO1FBRUQ7Ozs7OztXQU1HO1FBQ0gsZUFBVSxHQUFHLENBQUMsR0FBVyxFQUFVLEVBQUU7WUFDbkMsSUFBSSxHQUFHLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUU7Z0JBQy9CLE9BQU8sSUFBSSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUE7YUFDM0M7WUFDRCxNQUFNLElBQUksMEJBQWlCLENBQUMsNkNBQTZDLENBQUMsQ0FBQTtRQUM1RSxDQUFDLENBQUE7UUFFRDs7V0FFRztRQUNILG1CQUFjLEdBQUcsQ0FBQyxTQUFtQixFQUFFLE9BQVcsU0FBUyxFQUFXLEVBQUU7WUFDdEUsSUFBSSxHQUFPLENBQUE7WUFDWCxJQUFJLE9BQU8sSUFBSSxLQUFLLFdBQVcsRUFBRTtnQkFDL0IsR0FBRyxHQUFHLElBQUEseUJBQU8sR0FBRSxDQUFBO2FBQ2hCO2lCQUFNO2dCQUNMLEdBQUcsR0FBRyxJQUFJLENBQUE7YUFDWDtZQUNELE1BQU0sU0FBUyxHQUFhLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLEdBQUcsQ0FBQyxDQUFBO1lBQzVELE1BQU0sU0FBUyxHQUFXLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ3hELElBQUksU0FBUyxDQUFDLE1BQU0sSUFBSSxTQUFTLEVBQUU7Z0JBQ2pDLE9BQU8sSUFBSSxDQUFBO2FBQ1o7WUFFRCxPQUFPLEtBQUssQ0FBQTtRQUNkLENBQUMsQ0FBQTtRQUVEOztXQUVHO1FBQ0gsZ0JBQVcsR0FBRyxDQUFDLFNBQW1CLEVBQUUsT0FBVyxTQUFTLEVBQVksRUFBRTtZQUNwRSxNQUFNLFNBQVMsR0FBYSxFQUFFLENBQUE7WUFDOUIsSUFBSSxHQUFPLENBQUE7WUFDWCxJQUFJLE9BQU8sSUFBSSxLQUFLLFdBQVcsRUFBRTtnQkFDL0IsR0FBRyxHQUFHLElBQUEseUJBQU8sR0FBRSxDQUFBO2FBQ2hCO2lCQUFNO2dCQUNMLEdBQUcsR0FBRyxJQUFJLENBQUE7YUFDWDtZQUNELE1BQU0sUUFBUSxHQUFPLFFBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFBO1lBQzNELElBQUksR0FBRyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsRUFBRTtnQkFDckIsOEJBQThCO2dCQUM5QixPQUFPLFNBQVMsQ0FBQTthQUNqQjtZQUVELE1BQU0sU0FBUyxHQUFXLElBQUksQ0FBQyxTQUFTLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQ3hELEtBQ0UsSUFBSSxDQUFDLEdBQVcsQ0FBQyxFQUNqQixDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLElBQUksU0FBUyxDQUFDLE1BQU0sR0FBRyxTQUFTLEVBQ3pELENBQUMsRUFBRSxFQUNIO2dCQUNBLEtBQ0UsSUFBSSxDQUFDLEdBQVcsQ0FBQyxFQUNqQixDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sSUFBSSxTQUFTLENBQUMsTUFBTSxHQUFHLFNBQVMsRUFDcEQsQ0FBQyxFQUFFLEVBQ0g7b0JBQ0EsSUFDRSxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7d0JBQ2pDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsRUFDakQ7d0JBQ0EsU0FBUyxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7cUJBQ2xDO2lCQUNGO2FBQ0Y7WUFFRCxPQUFPLFNBQVMsQ0FBQTtRQUNsQixDQUFDLENBQUE7UUE0REMsSUFBSSxPQUFPLFNBQVMsS0FBSyxXQUFXLElBQUksU0FBUyxDQUFDLE1BQU0sRUFBRTtZQUN4RCxNQUFNLEtBQUssR0FBYyxFQUFFLENBQUE7WUFDM0IsS0FBSyxJQUFJLENBQUMsR0FBVyxDQUFDLEVBQUUsQ0FBQyxHQUFHLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ2pELEtBQUssQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxPQUFPLEVBQUUsQ0FBQTtnQkFDN0IsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO2FBQzVDO1lBQ0QsSUFBSSxDQUFDLFNBQVMsR0FBRyxLQUFLLENBQUE7WUFDdEIsSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUE7WUFDekMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUE7U0FDdEQ7UUFDRCxJQUFJLE9BQU8sU0FBUyxLQUFLLFNBQVMsRUFBRTtZQUNsQyxJQUFJLENBQUMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxTQUFTLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFBO1NBQ2hEO1FBQ0QsSUFBSSxPQUFPLFFBQVEsS0FBSyxXQUFXLEVBQUU7WUFDbkMsSUFBSSxDQUFDLFFBQVEsR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUMsQ0FBQTtTQUNyRDtJQUNILENBQUM7SUFFRCxNQUFNLENBQUMsU0FBUyxDQUFDLENBQVM7UUFDeEIsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFBLENBQUMsbUJBQW1CO1FBQ2xDLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDM0IsTUFBTSxNQUFNLEdBQW1CLEVBQUUsQ0FBQTtRQUNqQyxPQUFPLE1BQU0sR0FBRyxDQUFDLENBQUMsTUFBTSxJQUFJLEdBQUcsRUFBRSxHQUFHLENBQUMsRUFBRTtZQUNyQyxNQUFNLENBQUMsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFBO1lBQzVCLE1BQU0sR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQTtZQUNoQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO1NBQ2Y7UUFDRCxPQUFPLE1BQU0sQ0FBQTtJQUNmLENBQUM7SUFFRCxNQUFNLENBQUMsT0FBTyxDQUFDLENBQWlCO1FBQzlCLE1BQU0sZUFBZSxHQUFHLGVBQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDdkMsZUFBZSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFBO1FBQzFDLElBQUksS0FBSyxHQUFXLENBQUMsQ0FBQTtRQUNyQixNQUFNLElBQUksR0FBYSxDQUFDLGVBQWUsQ0FBQyxDQUFBO1FBQ3hDLEtBQUssTUFBTSxXQUFXLElBQUksQ0FBQyxFQUFFO1lBQzNCLE1BQU0sQ0FBQyxHQUFHLFdBQVcsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtZQUNoQyxLQUFLLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQTtZQUNqQixJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFBO1NBQ2I7UUFDRCxPQUFPLGVBQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxDQUFBO0lBQ25DLENBQUM7Q0FDRjtBQXBSRCxvQ0FvUkM7QUFFRCxNQUFzQixNQUFPLFNBQVEsWUFBWTtJQUFqRDs7UUFDWSxjQUFTLEdBQUcsUUFBUSxDQUFBO1FBQ3BCLFlBQU8sR0FBRyxTQUFTLENBQUE7SUFvQi9CLENBQUM7Q0FBQTtBQXRCRCx3QkFzQkM7QUFFRCxNQUFzQix1QkFBd0IsU0FBUSw0QkFBWTtJQUloRSxTQUFTLENBQUMsV0FBK0IsS0FBSztRQUM1QyxJQUFJLE1BQU0sR0FBVyxLQUFLLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQzlDLHVDQUNLLE1BQU0sS0FDVCxNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLElBQ3hDO0lBQ0gsQ0FBQztJQXFCRCxRQUFRO1FBQ04sTUFBTSxPQUFPLEdBQVcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEVBQUUsQ0FBQTtRQUM5QyxNQUFNLEtBQUssR0FBVyxlQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3JDLEtBQUssQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUNqRCxNQUFNLElBQUksR0FBYSxDQUFDLEtBQUssRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUN2QyxPQUFPLGVBQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLEtBQUssQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQzNELENBQUM7SUFFRCxZQUFZO1FBQ1YsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFBO0lBQ25DLENBQUM7SUFDRCxXQUFXO1FBQ1QsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFBO0lBQ2xDLENBQUM7SUFDRCxZQUFZO1FBQ1YsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFBO0lBQ25DLENBQUM7SUFFRCxjQUFjLENBQUMsS0FBZSxFQUFFLElBQVE7UUFDdEMsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUE7SUFDaEQsQ0FBQztJQUlEOzs7O09BSUc7SUFDSCxZQUFZLFNBQXFCLFNBQVM7UUFDeEMsS0FBSyxFQUFFLENBQUE7UUE1REMsY0FBUyxHQUFHLHlCQUF5QixDQUFBO1FBQ3JDLFlBQU8sR0FBRyxTQUFTLENBQUE7UUFtRDdCLGNBQVMsR0FBRyxHQUFlLEVBQUUsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFBO1FBU3ZDLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO0lBQ3RCLENBQUM7O0FBL0RILDBEQWdFQztBQWxEQzs7R0FFRztBQUNJLGtDQUFVLEdBQ2YsR0FHaUIsRUFBRSxDQUNuQixDQUFDLENBQTBCLEVBQUUsQ0FBMEIsRUFBYyxFQUFFO0lBQ3JFLE1BQU0sS0FBSyxHQUFHLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtJQUMxQixNQUFNLEtBQUssR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUE7SUFDMUIsT0FBTyxlQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQWUsQ0FBQTtBQUNuRCxDQUFDLENBQUE7QUF3Q0wsTUFBc0IsMEJBQTJCLFNBQVEsdUJBQXVCO0lBSTlFLFNBQVMsQ0FBQyxXQUErQixLQUFLO1FBQzVDLElBQUksTUFBTSxHQUFXLEtBQUssQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDOUMsdUNBQ0ssTUFBTSxLQUNULE9BQU8sRUFBRSxhQUFhLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsUUFBUSxFQUFFLFFBQVEsRUFBRSxNQUFNLENBQUMsSUFDekU7SUFDSCxDQUFDO0lBQ0QsV0FBVyxDQUFDLE1BQWMsRUFBRSxXQUErQixLQUFLO1FBQzlELEtBQUssQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFBO1FBQ25DLElBQUksQ0FBQyxPQUFPLEdBQUcsYUFBYSxDQUFDLE9BQU8sQ0FDbEMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUNqQixRQUFRLEVBQ1IsTUFBTSxFQUNOLFFBQVEsRUFDUixFQUFFLENBQ0gsQ0FBQTtJQUNILENBQUM7SUFTRCxRQUFRO1FBQ04sTUFBTSxhQUFhLEdBQVcsS0FBSyxDQUFDLFFBQVEsRUFBRSxDQUFBO1FBQzlDLE1BQU0sSUFBSSxHQUFhLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxhQUFhLENBQUMsQ0FBQTtRQUNwRCxPQUFPLGVBQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQTtJQUN4RSxDQUFDO0lBRUQ7Ozs7O09BS0c7SUFDSCxZQUFZLFVBQWtCLFNBQVMsRUFBRSxTQUFxQixTQUFTO1FBQ3JFLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQXpDTCxjQUFTLEdBQUcsNEJBQTRCLENBQUE7UUFDeEMsWUFBTyxHQUFHLFNBQVMsQ0FBQTtRQW9CbkIsWUFBTyxHQUFXLFNBQVMsQ0FBQTtRQUVyQyxlQUFVLEdBQUcsR0FBVyxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQTtRQW1CckMsSUFBSSxPQUFPLE9BQU8sS0FBSyxXQUFXLEVBQUU7WUFDbEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7U0FDdkI7SUFDSCxDQUFDO0NBQ0Y7QUEvQ0QsZ0VBK0NDO0FBRUQ7O0dBRUc7QUFDSCxNQUFzQixvQkFBcUIsU0FBUSxNQUFNO0lBSXZELFNBQVMsQ0FBQyxXQUErQixLQUFLO1FBQzVDLElBQUksTUFBTSxHQUFXLEtBQUssQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDOUMsdUNBQ0ssTUFBTSxLQUNULE1BQU0sRUFBRSxhQUFhLENBQUMsT0FBTyxDQUMzQixJQUFJLENBQUMsTUFBTSxFQUNYLFFBQVEsRUFDUixRQUFRLEVBQ1IsZUFBZSxFQUNmLENBQUMsQ0FDRixJQUNGO0lBQ0gsQ0FBQztJQUNELFdBQVcsQ0FBQyxNQUFjLEVBQUUsV0FBK0IsS0FBSztRQUM5RCxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQTtRQUNuQyxJQUFJLENBQUMsTUFBTSxHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQ2pDLE1BQU0sQ0FBQyxRQUFRLENBQUMsRUFDaEIsUUFBUSxFQUNSLGVBQWUsRUFDZixRQUFRLEVBQ1IsQ0FBQyxDQUNGLENBQUE7UUFDRCxJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFBO0lBQ3pELENBQUM7SUFLRDs7T0FFRztJQUNILFNBQVM7UUFDUCxPQUFPLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxFQUFFLENBQUE7SUFDakMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsVUFBVSxDQUFDLE9BQWUsRUFBRSxTQUFpQixDQUFDO1FBQzVDLElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtRQUM1RCxJQUFJLENBQUMsV0FBVyxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBQ3ZELE1BQU0sSUFBSSxDQUFDLENBQUE7UUFDWCxPQUFPLEtBQUssQ0FBQyxVQUFVLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxDQUFBO0lBQzFDLENBQUM7SUFFRDs7T0FFRztJQUNILFFBQVE7UUFDTixNQUFNLFNBQVMsR0FBVyxLQUFLLENBQUMsUUFBUSxFQUFFLENBQUE7UUFDMUMsTUFBTSxLQUFLLEdBQVcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEdBQUcsU0FBUyxDQUFDLE1BQU0sQ0FBQTtRQUMzRCxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQTtRQUNyRCxNQUFNLElBQUksR0FBYSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUUsU0FBUyxDQUFDLENBQUE7UUFDL0MsT0FBTyxlQUFNLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQTtJQUNuQyxDQUFDO0lBRUQ7Ozs7Ozs7T0FPRztJQUNILFlBQ0UsU0FBYSxTQUFTLEVBQ3RCLFlBQXNCLFNBQVMsRUFDL0IsV0FBZSxTQUFTLEVBQ3hCLFlBQW9CLFNBQVM7UUFFN0IsS0FBSyxDQUFDLFNBQVMsRUFBRSxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUE7UUF6RTdCLGNBQVMsR0FBRyxzQkFBc0IsQ0FBQTtRQUNsQyxZQUFPLEdBQUcsU0FBUyxDQUFBO1FBMkJuQixXQUFNLEdBQVcsZUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNoQyxnQkFBVyxHQUFPLElBQUksZUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBNkNuQyxJQUFJLE9BQU8sTUFBTSxLQUFLLFdBQVcsRUFBRTtZQUNqQyxJQUFJLENBQUMsV0FBVyxHQUFHLE1BQU0sQ0FBQyxLQUFLLEVBQUUsQ0FBQTtZQUNqQyxJQUFJLENBQUMsTUFBTSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFBO1NBQ2pEO0lBQ0gsQ0FBQztDQUNGO0FBaEZELG9EQWdGQztBQUVEOztHQUVHO0FBQ0gsTUFBc0IsYUFBYyxTQUFRLE1BQU07SUFBbEQ7O1FBQ1ksY0FBUyxHQUFHLGVBQWUsQ0FBQTtRQUMzQixZQUFPLEdBQUcsU0FBUyxDQUFBO1FBMEJuQixZQUFPLEdBQVcsZUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUUzQzs7V0FFRztRQUNILGVBQVUsR0FBRyxHQUFXLEVBQUU7WUFDeEIsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNyQyxDQUFDLENBQUE7SUFDSCxDQUFDO0lBaENDLFNBQVMsQ0FBQyxXQUErQixLQUFLO1FBQzVDLElBQUksTUFBTSxHQUFXLEtBQUssQ0FBQyxTQUFTLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDOUMsdUNBQ0ssTUFBTSxLQUNULE9BQU8sRUFBRSxhQUFhLENBQUMsT0FBTyxDQUM1QixJQUFJLENBQUMsT0FBTyxFQUNaLFFBQVEsRUFDUixRQUFRLEVBQ1IsZUFBZSxFQUNmLENBQUMsQ0FDRixJQUNGO0lBQ0gsQ0FBQztJQUNELFdBQVcsQ0FBQyxNQUFjLEVBQUUsV0FBK0IsS0FBSztRQUM5RCxLQUFLLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxRQUFRLENBQUMsQ0FBQTtRQUNuQyxJQUFJLENBQUMsT0FBTyxHQUFHLGFBQWEsQ0FBQyxPQUFPLENBQ2xDLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFDakIsUUFBUSxFQUNSLGVBQWUsRUFDZixRQUFRLEVBQ1IsQ0FBQyxDQUNGLENBQUE7SUFDSCxDQUFDO0NBVUY7QUFwQ0Qsc0NBb0NDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBAcGFja2FnZURvY3VtZW50YXRpb25cbiAqIEBtb2R1bGUgQ29tbW9uLU91dHB1dFxuICovXG5cbmltcG9ydCB7IEJ1ZmZlciB9IGZyb20gXCJidWZmZXIvXCJcbmltcG9ydCBCTiBmcm9tIFwiYm4uanNcIlxuaW1wb3J0IEJpblRvb2xzIGZyb20gXCIuLi91dGlscy9iaW50b29sc1wiXG5pbXBvcnQgeyBOQnl0ZXMgfSBmcm9tIFwiLi9uYnl0ZXNcIlxuaW1wb3J0IHsgVW5peE5vdyB9IGZyb20gXCIuLi91dGlscy9oZWxwZXJmdW5jdGlvbnNcIlxuaW1wb3J0IHtcbiAgU2VyaWFsaXphYmxlLFxuICBTZXJpYWxpemF0aW9uLFxuICBTZXJpYWxpemVkRW5jb2Rpbmdcbn0gZnJvbSBcIi4uL3V0aWxzL3NlcmlhbGl6YXRpb25cIlxuaW1wb3J0IHsgQ2hlY2tzdW1FcnJvciwgQWRkcmVzc0Vycm9yLCBBZGRyZXNzSW5kZXhFcnJvciB9IGZyb20gXCIuLi91dGlscy9lcnJvcnNcIlxuXG4vKipcbiAqIEBpZ25vcmVcbiAqL1xuY29uc3QgYmludG9vbHM6IEJpblRvb2xzID0gQmluVG9vbHMuZ2V0SW5zdGFuY2UoKVxuY29uc3Qgc2VyaWFsaXphdGlvbjogU2VyaWFsaXphdGlvbiA9IFNlcmlhbGl6YXRpb24uZ2V0SW5zdGFuY2UoKVxuXG5leHBvcnQgaW50ZXJmYWNlIEJhc2VPdXRwdXQge1xuICBnZXRUeXBlSUQoKTogbnVtYmVyXG5cbiAgc2VyaWFsaXplKGVuY29kaW5nOiBTZXJpYWxpemVkRW5jb2RpbmcpOiBvYmplY3RcbiAgZGVzZXJpYWxpemUoZmllbGRzOiBvYmplY3QsIGVuY29kaW5nOiBTZXJpYWxpemVkRW5jb2RpbmcpOiB2b2lkXG4gIGZyb21CdWZmZXIoYnl0ZXM6IEJ1ZmZlciwgb2Zmc2V0OiBudW1iZXIpOiBudW1iZXJcbiAgdG9CdWZmZXIoKTogQnVmZmVyXG5cbiAgZ2V0VGhyZXNob2xkKCk6IG51bWJlclxuICBnZXRMb2NrdGltZSgpOiBCTlxuICBnZXRBZGRyZXNzZXMoKTogQnVmZmVyW11cbiAgbWVldHNUaHJlc2hvbGQoYWRkcnM6IEJ1ZmZlcltdLCBhc09mOiBCTik6IGJvb2xlYW5cblxuICBnZXRPdXRwdXRJRCgpOiBudW1iZXJcbiAgY2xvbmUoKTogdGhpc1xuICBjcmVhdGUoLi4uYXJnczogYW55W10pOiB0aGlzXG59XG5cbmV4cG9ydCBjb25zdCBCYXNlT3V0cHV0Q29tcGFyYXRvciA9XG4gICgpOiAoKGE6IEJhc2VPdXRwdXQsIGI6IEJhc2VPdXRwdXQpID0+IDEgfCAtMSB8IDApID0+XG4gIChhOiBCYXNlT3V0cHV0LCBiOiBCYXNlT3V0cHV0KTogMSB8IC0xIHwgMCA9PiB7XG4gICAgY29uc3QgYW91dGlkOiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoNClcbiAgICBhb3V0aWQud3JpdGVVSW50MzJCRShhLmdldE91dHB1dElEKCksIDApXG4gICAgY29uc3QgYWJ1ZmY6IEJ1ZmZlciA9IGEudG9CdWZmZXIoKVxuXG4gICAgY29uc3QgYm91dGlkOiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoNClcbiAgICBib3V0aWQud3JpdGVVSW50MzJCRShiLmdldE91dHB1dElEKCksIDApXG4gICAgY29uc3QgYmJ1ZmY6IEJ1ZmZlciA9IGIudG9CdWZmZXIoKVxuXG4gICAgY29uc3QgYXNvcnQ6IEJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoXG4gICAgICBbYW91dGlkLCBhYnVmZl0sXG4gICAgICBhb3V0aWQubGVuZ3RoICsgYWJ1ZmYubGVuZ3RoXG4gICAgKVxuICAgIGNvbnN0IGJzb3J0OiBCdWZmZXIgPSBCdWZmZXIuY29uY2F0KFxuICAgICAgW2JvdXRpZCwgYmJ1ZmZdLFxuICAgICAgYm91dGlkLmxlbmd0aCArIGJidWZmLmxlbmd0aFxuICAgIClcbiAgICByZXR1cm4gQnVmZmVyLmNvbXBhcmUoYXNvcnQsIGJzb3J0KSBhcyAxIHwgLTEgfCAwXG4gIH1cblxuLyoqXG4gKiBDbGFzcyBmb3IgcmVwcmVzZW50aW5nIGFuIGFkZHJlc3MgdXNlZCBpbiBbW091dHB1dF1dIHR5cGVzXG4gKi9cbmV4cG9ydCBjbGFzcyBBZGRyZXNzIGV4dGVuZHMgTkJ5dGVzIHtcbiAgcHJvdGVjdGVkIF90eXBlTmFtZSA9IFwiQWRkcmVzc1wiXG4gIHByb3RlY3RlZCBfdHlwZUlEID0gdW5kZWZpbmVkXG5cbiAgLy9zZXJpYWxpemUgYW5kIGRlc2VyaWFsaXplIGJvdGggYXJlIGluaGVyaXRlZFxuXG4gIHByb3RlY3RlZCBieXRlcyA9IEJ1ZmZlci5hbGxvYygyMClcbiAgcHJvdGVjdGVkIGJzaXplID0gMjBcblxuICAvKipcbiAgICogUmV0dXJucyBhIGZ1bmN0aW9uIHVzZWQgdG8gc29ydCBhbiBhcnJheSBvZiBbW0FkZHJlc3NdXWVzXG4gICAqL1xuICBzdGF0aWMgY29tcGFyYXRvciA9XG4gICAgKCk6ICgoYTogQWRkcmVzcywgYjogQWRkcmVzcykgPT4gMSB8IC0xIHwgMCkgPT5cbiAgICAoYTogQWRkcmVzcywgYjogQWRkcmVzcyk6IDEgfCAtMSB8IDAgPT5cbiAgICAgIEJ1ZmZlci5jb21wYXJlKGEudG9CdWZmZXIoKSwgYi50b0J1ZmZlcigpKSBhcyAxIHwgLTEgfCAwXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYSBiYXNlLTU4IHJlcHJlc2VudGF0aW9uIG9mIHRoZSBbW0FkZHJlc3NdXS5cbiAgICovXG4gIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGJpbnRvb2xzLmNiNThFbmNvZGUodGhpcy50b0J1ZmZlcigpKVxuICB9XG5cbiAgLyoqXG4gICAqIFRha2VzIGEgYmFzZS01OCBzdHJpbmcgY29udGFpbmluZyBhbiBbW0FkZHJlc3NdXSwgcGFyc2VzIGl0LCBwb3B1bGF0ZXMgdGhlIGNsYXNzLCBhbmQgcmV0dXJucyB0aGUgbGVuZ3RoIG9mIHRoZSBBZGRyZXNzIGluIGJ5dGVzLlxuICAgKlxuICAgKiBAcGFyYW0gYnl0ZXMgQSBiYXNlLTU4IHN0cmluZyBjb250YWluaW5nIGEgcmF3IFtbQWRkcmVzc11dXG4gICAqXG4gICAqIEByZXR1cm5zIFRoZSBsZW5ndGggb2YgdGhlIHJhdyBbW0FkZHJlc3NdXVxuICAgKi9cbiAgZnJvbVN0cmluZyhhZGRyOiBzdHJpbmcpOiBudW1iZXIge1xuICAgIGNvbnN0IGFkZHJidWZmOiBCdWZmZXIgPSBiaW50b29scy5iNThUb0J1ZmZlcihhZGRyKVxuICAgIGlmIChhZGRyYnVmZi5sZW5ndGggPT09IDI0ICYmIGJpbnRvb2xzLnZhbGlkYXRlQ2hlY2tzdW0oYWRkcmJ1ZmYpKSB7XG4gICAgICBjb25zdCBuZXdidWZmOiBCdWZmZXIgPSBiaW50b29scy5jb3B5RnJvbShcbiAgICAgICAgYWRkcmJ1ZmYsXG4gICAgICAgIDAsXG4gICAgICAgIGFkZHJidWZmLmxlbmd0aCAtIDRcbiAgICAgIClcbiAgICAgIGlmIChuZXdidWZmLmxlbmd0aCA9PT0gMjApIHtcbiAgICAgICAgdGhpcy5ieXRlcyA9IG5ld2J1ZmZcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGFkZHJidWZmLmxlbmd0aCA9PT0gMjQpIHtcbiAgICAgIHRocm93IG5ldyBDaGVja3N1bUVycm9yKFxuICAgICAgICBcIkVycm9yIC0gQWRkcmVzcy5mcm9tU3RyaW5nOiBpbnZhbGlkIGNoZWNrc3VtIG9uIGFkZHJlc3NcIlxuICAgICAgKVxuICAgIH0gZWxzZSBpZiAoYWRkcmJ1ZmYubGVuZ3RoID09PSAyMCkge1xuICAgICAgdGhpcy5ieXRlcyA9IGFkZHJidWZmXG4gICAgfSBlbHNlIHtcbiAgICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgICB0aHJvdyBuZXcgQWRkcmVzc0Vycm9yKFwiRXJyb3IgLSBBZGRyZXNzLmZyb21TdHJpbmc6IGludmFsaWQgYWRkcmVzc1wiKVxuICAgIH1cbiAgICByZXR1cm4gdGhpcy5nZXRTaXplKClcbiAgfVxuXG4gIGNsb25lKCk6IHRoaXMge1xuICAgIGxldCBuZXdiYXNlOiBBZGRyZXNzID0gbmV3IEFkZHJlc3MoKVxuICAgIG5ld2Jhc2UuZnJvbUJ1ZmZlcih0aGlzLnRvQnVmZmVyKCkpXG4gICAgcmV0dXJuIG5ld2Jhc2UgYXMgdGhpc1xuICB9XG5cbiAgY3JlYXRlKCk6IHRoaXMge1xuICAgIHJldHVybiBuZXcgQWRkcmVzcygpIGFzIHRoaXNcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGFzcyBmb3IgcmVwcmVzZW50aW5nIGFuIGFkZHJlc3MgdXNlZCBpbiBbW091dHB1dF1dIHR5cGVzXG4gICAqL1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBzdXBlcigpXG4gIH1cbn1cblxuLyoqXG4gKiBEZWZpbmVzIHRoZSBtb3N0IGJhc2ljIHZhbHVlcyBmb3Igb3V0cHV0IG93bmVyc2hpcC4gTW9zdGx5IGluaGVyaXRlZCBmcm9tLCBidXQgY2FuIGJlIHVzZWQgaW4gcG9wdWxhdGlvbiBvZiBORlQgT3duZXIgZGF0YS5cbiAqL1xuZXhwb3J0IGNsYXNzIE91dHB1dE93bmVycyBleHRlbmRzIFNlcmlhbGl6YWJsZSB7XG4gIHByb3RlY3RlZCBfdHlwZU5hbWUgPSBcIk91dHB1dE93bmVyc1wiXG4gIHByb3RlY3RlZCBfdHlwZUlEID0gdW5kZWZpbmVkXG5cbiAgc2VyaWFsaXplKGVuY29kaW5nOiBTZXJpYWxpemVkRW5jb2RpbmcgPSBcImhleFwiKTogb2JqZWN0IHtcbiAgICBsZXQgZmllbGRzOiBvYmplY3QgPSBzdXBlci5zZXJpYWxpemUoZW5jb2RpbmcpXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLmZpZWxkcyxcbiAgICAgIGxvY2t0aW1lOiBzZXJpYWxpemF0aW9uLmVuY29kZXIoXG4gICAgICAgIHRoaXMubG9ja3RpbWUsXG4gICAgICAgIGVuY29kaW5nLFxuICAgICAgICBcIkJ1ZmZlclwiLFxuICAgICAgICBcImRlY2ltYWxTdHJpbmdcIixcbiAgICAgICAgOFxuICAgICAgKSxcbiAgICAgIHRocmVzaG9sZDogc2VyaWFsaXphdGlvbi5lbmNvZGVyKFxuICAgICAgICB0aGlzLnRocmVzaG9sZCxcbiAgICAgICAgZW5jb2RpbmcsXG4gICAgICAgIFwiQnVmZmVyXCIsXG4gICAgICAgIFwiZGVjaW1hbFN0cmluZ1wiLFxuICAgICAgICA0XG4gICAgICApLFxuICAgICAgYWRkcmVzc2VzOiB0aGlzLmFkZHJlc3Nlcy5tYXAoKGE6IEFkZHJlc3MpOiBvYmplY3QgPT5cbiAgICAgICAgYS5zZXJpYWxpemUoZW5jb2RpbmcpXG4gICAgICApXG4gICAgfVxuICB9XG4gIGRlc2VyaWFsaXplKGZpZWxkczogb2JqZWN0LCBlbmNvZGluZzogU2VyaWFsaXplZEVuY29kaW5nID0gXCJoZXhcIikge1xuICAgIHN1cGVyLmRlc2VyaWFsaXplKGZpZWxkcywgZW5jb2RpbmcpXG4gICAgdGhpcy5sb2NrdGltZSA9IHNlcmlhbGl6YXRpb24uZGVjb2RlcihcbiAgICAgIGZpZWxkc1tcImxvY2t0aW1lXCJdLFxuICAgICAgZW5jb2RpbmcsXG4gICAgICBcImRlY2ltYWxTdHJpbmdcIixcbiAgICAgIFwiQnVmZmVyXCIsXG4gICAgICA4XG4gICAgKVxuICAgIHRoaXMudGhyZXNob2xkID0gc2VyaWFsaXphdGlvbi5kZWNvZGVyKFxuICAgICAgZmllbGRzW1widGhyZXNob2xkXCJdLFxuICAgICAgZW5jb2RpbmcsXG4gICAgICBcImRlY2ltYWxTdHJpbmdcIixcbiAgICAgIFwiQnVmZmVyXCIsXG4gICAgICA0XG4gICAgKVxuICAgIHRoaXMuYWRkcmVzc2VzID0gZmllbGRzW1wiYWRkcmVzc2VzXCJdLm1hcCgoYTogb2JqZWN0KSA9PiB7XG4gICAgICBsZXQgYWRkcjogQWRkcmVzcyA9IG5ldyBBZGRyZXNzKClcbiAgICAgIGFkZHIuZGVzZXJpYWxpemUoYSwgZW5jb2RpbmcpXG4gICAgICByZXR1cm4gYWRkclxuICAgIH0pXG4gICAgdGhpcy5udW1hZGRycyA9IEJ1ZmZlci5hbGxvYyg0KVxuICAgIHRoaXMubnVtYWRkcnMud3JpdGVVSW50MzJCRSh0aGlzLmFkZHJlc3Nlcy5sZW5ndGgsIDApXG4gIH1cblxuICBwcm90ZWN0ZWQgbG9ja3RpbWU6IEJ1ZmZlciA9IEJ1ZmZlci5hbGxvYyg4KVxuICBwcm90ZWN0ZWQgdGhyZXNob2xkOiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoNClcbiAgcHJvdGVjdGVkIG51bWFkZHJzOiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoNClcbiAgcHJvdGVjdGVkIGFkZHJlc3NlczogQWRkcmVzc1tdID0gW11cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgdGhyZXNob2xkIG9mIHNpZ25lcnMgcmVxdWlyZWQgdG8gc3BlbmQgdGhpcyBvdXRwdXQuXG4gICAqL1xuICBnZXRUaHJlc2hvbGQgPSAoKTogbnVtYmVyID0+IHRoaXMudGhyZXNob2xkLnJlYWRVSW50MzJCRSgwKVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBhIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vaW5kdXRueS9ibi5qcy98Qk59IHJlcGVyc2VudGluZyB0aGUgVU5JWCBUaW1lc3RhbXAgd2hlbiB0aGUgbG9jayBpcyBtYWRlIGF2YWlsYWJsZS5cbiAgICovXG4gIGdldExvY2t0aW1lID0gKCk6IEJOID0+IGJpbnRvb2xzLmZyb21CdWZmZXJUb0JOKHRoaXMubG9ja3RpbWUpXG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gYXJyYXkgb2Yge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn1zIGZvciB0aGUgYWRkcmVzc2VzLlxuICAgKi9cbiAgZ2V0QWRkcmVzc2VzID0gKCk6IEJ1ZmZlcltdID0+IHtcbiAgICBjb25zdCByZXN1bHQ6IEJ1ZmZlcltdID0gW11cbiAgICBmb3IgKGxldCBpOiBudW1iZXIgPSAwOyBpIDwgdGhpcy5hZGRyZXNzZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHJlc3VsdC5wdXNoKHRoaXMuYWRkcmVzc2VzW2Ake2l9YF0udG9CdWZmZXIoKSlcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgYW4gdGhlIGxlbmd0aCBvZiB0aGUgQWRkcmVzc2VzIGFycmF5LlxuICAgKi9cbiAgZ2V0QWRkcmVzc2VzTGVuZ3RoID0gKCk6IG51bWJlciA9PiB0aGlzLmFkZHJlc3Nlcy5sZW5ndGhcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaW5kZXggb2YgdGhlIGFkZHJlc3MuXG4gICAqXG4gICAqIEBwYXJhbSBhZGRyZXNzIEEge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn0gb2YgdGhlIGFkZHJlc3MgdG8gbG9vayB1cCB0byByZXR1cm4gaXRzIGluZGV4LlxuICAgKlxuICAgKiBAcmV0dXJucyBUaGUgaW5kZXggb2YgdGhlIGFkZHJlc3MuXG4gICAqL1xuICBnZXRBZGRyZXNzSWR4ID0gKGFkZHJlc3M6IEJ1ZmZlcik6IG51bWJlciA9PiB7XG4gICAgZm9yIChsZXQgaTogbnVtYmVyID0gMDsgaSA8IHRoaXMuYWRkcmVzc2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAoXG4gICAgICAgIHRoaXMuYWRkcmVzc2VzW2Ake2l9YF0udG9CdWZmZXIoKS50b1N0cmluZyhcImhleFwiKSA9PT1cbiAgICAgICAgYWRkcmVzcy50b1N0cmluZyhcImhleFwiKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBpXG4gICAgICB9XG4gICAgfVxuICAgIC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG4gICAgcmV0dXJuIC0xXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgYWRkcmVzcyBmcm9tIHRoZSBpbmRleCBwcm92aWRlZC5cbiAgICpcbiAgICogQHBhcmFtIGlkeCBUaGUgaW5kZXggb2YgdGhlIGFkZHJlc3MuXG4gICAqXG4gICAqIEByZXR1cm5zIFJldHVybnMgdGhlIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGFkZHJlc3MuXG4gICAqL1xuICBnZXRBZGRyZXNzID0gKGlkeDogbnVtYmVyKTogQnVmZmVyID0+IHtcbiAgICBpZiAoaWR4IDwgdGhpcy5hZGRyZXNzZXMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gdGhpcy5hZGRyZXNzZXNbYCR7aWR4fWBdLnRvQnVmZmVyKClcbiAgICB9XG4gICAgdGhyb3cgbmV3IEFkZHJlc3NJbmRleEVycm9yKFwiRXJyb3IgLSBPdXRwdXQuZ2V0QWRkcmVzczogaWR4IG91dCBvZiByYW5nZVwiKVxuICB9XG5cbiAgLyoqXG4gICAqIEdpdmVuIGFuIGFycmF5IG9mIGFkZHJlc3Mge0BsaW5rIGh0dHBzOi8vZ2l0aHViLmNvbS9mZXJvc3MvYnVmZmVyfEJ1ZmZlcn1zIGFuZCBhbiBvcHRpb25hbCB0aW1lc3RhbXAsIHJldHVybnMgdHJ1ZSBpZiB0aGUgYWRkcmVzc2VzIG1lZXQgdGhlIHRocmVzaG9sZCByZXF1aXJlZCB0byBzcGVuZCB0aGUgb3V0cHV0LlxuICAgKi9cbiAgbWVldHNUaHJlc2hvbGQgPSAoYWRkcmVzc2VzOiBCdWZmZXJbXSwgYXNPZjogQk4gPSB1bmRlZmluZWQpOiBib29sZWFuID0+IHtcbiAgICBsZXQgbm93OiBCTlxuICAgIGlmICh0eXBlb2YgYXNPZiA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgbm93ID0gVW5peE5vdygpXG4gICAgfSBlbHNlIHtcbiAgICAgIG5vdyA9IGFzT2ZcbiAgICB9XG4gICAgY29uc3QgcXVhbGlmaWVkOiBCdWZmZXJbXSA9IHRoaXMuZ2V0U3BlbmRlcnMoYWRkcmVzc2VzLCBub3cpXG4gICAgY29uc3QgdGhyZXNob2xkOiBudW1iZXIgPSB0aGlzLnRocmVzaG9sZC5yZWFkVUludDMyQkUoMClcbiAgICBpZiAocXVhbGlmaWVkLmxlbmd0aCA+PSB0aHJlc2hvbGQpIHtcbiAgICAgIHJldHVybiB0cnVlXG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYW4gYXJyYXkgb2YgYWRkcmVzc2VzIGFuZCBhbiBvcHRpb25hbCB0aW1lc3RhbXAsIHNlbGVjdCBhbiBhcnJheSBvZiBhZGRyZXNzIHtAbGluayBodHRwczovL2dpdGh1Yi5jb20vZmVyb3NzL2J1ZmZlcnxCdWZmZXJ9cyBvZiBxdWFsaWZpZWQgc3BlbmRlcnMgZm9yIHRoZSBvdXRwdXQuXG4gICAqL1xuICBnZXRTcGVuZGVycyA9IChhZGRyZXNzZXM6IEJ1ZmZlcltdLCBhc09mOiBCTiA9IHVuZGVmaW5lZCk6IEJ1ZmZlcltdID0+IHtcbiAgICBjb25zdCBxdWFsaWZpZWQ6IEJ1ZmZlcltdID0gW11cbiAgICBsZXQgbm93OiBCTlxuICAgIGlmICh0eXBlb2YgYXNPZiA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAgICAgbm93ID0gVW5peE5vdygpXG4gICAgfSBlbHNlIHtcbiAgICAgIG5vdyA9IGFzT2ZcbiAgICB9XG4gICAgY29uc3QgbG9ja3RpbWU6IEJOID0gYmludG9vbHMuZnJvbUJ1ZmZlclRvQk4odGhpcy5sb2NrdGltZSlcbiAgICBpZiAobm93Lmx0ZShsb2NrdGltZSkpIHtcbiAgICAgIC8vIG5vdCB1bmxvY2tlZCwgbm90IHNwZW5kYWJsZVxuICAgICAgcmV0dXJuIHF1YWxpZmllZFxuICAgIH1cblxuICAgIGNvbnN0I