metaapi.cloud-sdk
Version:
SDK for MetaApi, a professional cloud forex API which includes MetaTrader REST API and MetaTrader websocket API. Supports both MetaTrader 5 (MT5) and MetaTrader 4 (MT4). CopyFactory copy trading API included. (https://metaapi.cloud)
253 lines (252 loc) • 40.9 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return SynchronizationListener;
}
});
let SynchronizationListener = class SynchronizationListener {
/**
* Returns region of instance index
* @param {String} instanceIndex instance index
*/ getRegion(instanceIndex) {
return typeof instanceIndex === "string" ? instanceIndex.split(":")[0] : undefined;
}
/**
* Returns instance number of instance index
* @param {String} instanceIndex instance index
*/ getInstanceNumber(instanceIndex) {
return typeof instanceIndex === "string" ? Number(instanceIndex.split(":")[1]) : undefined;
}
/**
* Returns host name of instance index
* @param {String} instanceIndex instance index
*/ getHostName(instanceIndex) {
return typeof instanceIndex === "string" ? instanceIndex.split(":")[2] : undefined;
}
/**
* Invoked when connection to MetaTrader terminal established
* @param {String} instanceIndex index of an account instance connected
* @param {Number} replicas number of account replicas launched
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onConnected(instanceIndex, replicas) {}
/**
* Server-side application health status
* @typedef {Object} healthStatus
* @property {boolean} [restApiHealthy] flag indicating that REST API is healthy
* @property {boolean} [copyFactorySubscriberHealthy] flag indicating that CopyFactory subscriber is healthy
* @property {boolean} [copyFactoryProviderHealthy] flag indicating that CopyFactory provider is healthy
*/ /**
* Invoked when a server-side application health status is received from MetaApi
* @param {String} instanceIndex index of an account instance connected
* @param {HealthStatus} status server-side application health status
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onHealthStatus(instanceIndex, status) {}
/**
* Invoked when connection to MetaTrader terminal terminated
* @param {String} instanceIndex index of an account instance connected
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onDisconnected(instanceIndex) {}
/**
* Invoked when broker connection satus have changed
* @param {String} instanceIndex index of an account instance connected
* @param {Boolean} connected is MetaTrader terminal is connected to broker
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onBrokerConnectionStatusChanged(instanceIndex, connected) {}
/**
* Invoked when MetaTrader terminal state synchronization is started
* @param {string} instanceIndex index of an account instance connected
* @param {string} specificationsHash specifications hash
* @param {string} positionsHash positions hash
* @param {string} ordersHash orders hash
* @param {string} synchronizationId synchronization id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onSynchronizationStarted(instanceIndex, specificationsHash, positionsHash, ordersHash, synchronizationId) {}
/**
* Invoked when MetaTrader account information is updated
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderAccountInformation} accountInformation updated MetaTrader account information
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onAccountInformationUpdated(instanceIndex, accountInformation) {}
/**
* Invoked when the positions are replaced as a result of initial terminal state synchronization. This method
* will be invoked only if server thinks the data was updated, otherwise invocation can be skipped
* @param {String} instanceIndex index of an account instance connected
* @param {Array<MetatraderPosition>} positions updated array of positions
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPositionsReplaced(instanceIndex, positions) {}
/**
* Invoked when position synchronization fnished to indicate progress of an initial terminal state synchronization
* @param {string} instanceIndex index of an account instance connected
* @param {String} synchronizationId synchronization request id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPositionsSynchronized(instanceIndex, synchronizationId) {}
/**
* Invoked when MetaTrader positions are updated
* @param {string} instanceIndex index of an account instance connected
* @param {MetatraderPosition[]} positions updated MetaTrader positions
* @param {string[]} removedPositionIds removed position ids
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPositionsUpdated(instanceIndex, positions, removedPositionIds) {}
/**
* Invoked when MetaTrader position is updated
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderPosition} position updated MetaTrader position
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPositionUpdated(instanceIndex, position) {}
/**
* Invoked when MetaTrader position is removed
* @param {String} instanceIndex index of an account instance connected
* @param {String} positionId removed MetaTrader position id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPositionRemoved(instanceIndex, positionId) {}
/**
* Invoked when the pending orders are replaced as a result of initial terminal state synchronization. This method
* will be invoked only if server thinks the data was updated, otherwise invocation can be skipped
* @param {String} instanceIndex index of an account instance connected
* @param {Array<MetatraderOrder>} orders updated array of pending orders
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPendingOrdersReplaced(instanceIndex, orders) {}
/**
* Invoked when MetaTrader pending orders are updated or completed
* @param {string} instanceIndex index of an account instance connected
* @param {MetatraderOrder[]} orders updated MetaTrader pending orders
* @param {string[]} completedOrderIds completed MetaTrader pending order ids
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPendingOrdersUpdated(instanceIndex, orders, completedOrderIds) {}
/**
* Invoked when MetaTrader pending order is updated
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderOrder} order updated MetaTrader pending order
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPendingOrderUpdated(instanceIndex, order) {}
/**
* Invoked when MetaTrader pending order is completed (executed or canceled)
* @param {String} instanceIndex index of an account instance connected
* @param {String} orderId completed MetaTrader pending order id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPendingOrderCompleted(instanceIndex, orderId) {}
/**
* Invoked when pending order synchronization fnished to indicate progress of an initial terminal state
* synchronization
* @param {string} instanceIndex index of an account instance connected
* @param {String} synchronizationId synchronization request id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onPendingOrdersSynchronized(instanceIndex, synchronizationId) {}
/**
* Invoked when a new MetaTrader history order is added
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderOrder} historyOrder new MetaTrader history order
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onHistoryOrderAdded(instanceIndex, historyOrder) {}
/**
* Invoked when a synchronization of history orders on a MetaTrader account have finished to indicate progress of an
* initial terminal state synchronization
* @param {String} instanceIndex index of an account instance connected
* @param {String} synchronizationId synchronization request id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onHistoryOrdersSynchronized(instanceIndex, synchronizationId) {}
/**
* Invoked when a new MetaTrader history deal is added
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderDeal} deal new MetaTrader history deal
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onDealAdded(instanceIndex, deal) {}
/**
* Invoked when a synchronization of history deals on a MetaTrader account have finished to indicate progress of an
* initial terminal state synchronization
* @param {String} instanceIndex index of an account instance connected
* @param {String} synchronizationId synchronization request id
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onDealsSynchronized(instanceIndex, synchronizationId) {}
/**
* Invoked when a symbol specification was updated
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderSymbolSpecification} specification updated MetaTrader symbol specification
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onSymbolSpecificationUpdated(instanceIndex, specification) {}
/**
* Invoked when a symbol specification was removed
* @param {String} instanceIndex index of an account instance connected
* @param {String} symbol removed symbol
* @returns {Promise} promise which resolves when the asynchronous event is processed
*/ async onSymbolSpecificationRemoved(instanceIndex, symbol) {}
/**
* Invoked when a symbol specifications were updated
* @param {String} instanceIndex index of account instance connected
* @param {Array<MetatraderSymbolSpecification>} specifications updated specifications
* @param {Array<String>} removedSymbols removed symbols
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onSymbolSpecificationsUpdated(instanceIndex, specifications, removedSymbols) {}
/**
* Invoked when a symbol price was updated
* @param {String} instanceIndex index of an account instance connected
* @param {MetatraderSymbolPrice} price updated MetaTrader symbol price
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onSymbolPriceUpdated(instanceIndex, price) {}
/**
* Invoked when prices for several symbols were updated
* @param {String} instanceIndex index of an account instance connected
* @param {Array<MetatraderSymbolPrice>} prices updated MetaTrader symbol prices
* @param {Number} equity account liquidation value
* @param {Number} margin margin used
* @param {Number} freeMargin free margin
* @param {Number} marginLevel margin level calculated as % of equity/margin
* @param {Number} accountCurrencyExchangeRate current exchange rate of account currency into USD
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onSymbolPricesUpdated(instanceIndex, prices, equity, margin, freeMargin, marginLevel, accountCurrencyExchangeRate) {}
/**
* Invoked when symbol candles were updated
* @param {String} instanceIndex index of an account instance connected
* @param {Array<MetatraderCandle>} candles updated MetaTrader symbol candles
* @param {Number} equity account liquidation value
* @param {Number} margin margin used
* @param {Number} freeMargin free margin
* @param {Number} marginLevel margin level calculated as % of equity/margin
* @param {Number} accountCurrencyExchangeRate current exchange rate of account currency into USD
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onCandlesUpdated(instanceIndex, candles, equity, margin, freeMargin, marginLevel, accountCurrencyExchangeRate) {}
/**
* Invoked when symbol ticks were updated
* @param {String} instanceIndex index of an account instance connected
* @param {Array<MetatraderTick>} ticks updated MetaTrader symbol ticks
* @param {Number} equity account liquidation value
* @param {Number} margin margin used
* @param {Number} freeMargin free margin
* @param {Number} marginLevel margin level calculated as % of equity/margin
* @param {Number} accountCurrencyExchangeRate current exchange rate of account currency into USD
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onTicksUpdated(instanceIndex, ticks, equity, margin, freeMargin, marginLevel, accountCurrencyExchangeRate) {}
/**
* Invoked when order books were updated
* @param {String} instanceIndex index of an account instance connected
* @param {Array<MetatraderBook>} books updated MetaTrader order books
* @param {Number} equity account liquidation value
* @param {Number} margin margin used
* @param {Number} freeMargin free margin
* @param {Number} marginLevel margin level calculated as % of equity/margin
* @param {Number} accountCurrencyExchangeRate current exchange rate of account currency into USD
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onBooksUpdated(instanceIndex, books, equity, margin, freeMargin, marginLevel, accountCurrencyExchangeRate) {}
/**
* Invoked when subscription downgrade has occurred
* @param {String} instanceIndex index of an account instance connected
* @param {string} symbol symbol to update subscriptions for
* @param {Array<MarketDataSubscription>} updates array of market data subscription to update
* @param {Array<MarketDataUnsubscription>} unsubscriptions array of subscriptions to cancel
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onSubscriptionDowngraded(instanceIndex, symbol, updates, unsubscriptions) {}
/**
* Invoked when a stream for an instance index is closed
* @param {String} instanceIndex index of an account instance connected
*/ async onStreamClosed(instanceIndex) {}
/**
* Invoked when account region has been unsubscribed
* @param {String} region account region unsubscribed
* @return {Promise} promise which resolves when the asynchronous event is processed
*/ async onUnsubscribeRegion(region) {}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogRGVmaW5lcyBpbnRlcmZhY2UgZm9yIGEgc3luY2hyb25pemF0aW9uIGxpc3RlbmVyIGNsYXNzXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFN5bmNocm9uaXphdGlvbkxpc3RlbmVyIHtcblxuICAvKipcbiAgICogUmV0dXJucyByZWdpb24gb2YgaW5zdGFuY2UgaW5kZXhcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5zdGFuY2UgaW5kZXhcbiAgICovXG4gIGdldFJlZ2lvbihpbnN0YW5jZUluZGV4KSB7XG4gICAgcmV0dXJuIHR5cGVvZiBpbnN0YW5jZUluZGV4ID09PSAnc3RyaW5nJyA/IGluc3RhbmNlSW5kZXguc3BsaXQoJzonKVswXSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGluc3RhbmNlIG51bWJlciBvZiBpbnN0YW5jZSBpbmRleFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbnN0YW5jZSBpbmRleFxuICAgKi9cbiAgZ2V0SW5zdGFuY2VOdW1iZXIoaW5zdGFuY2VJbmRleCkge1xuICAgIHJldHVybiB0eXBlb2YgaW5zdGFuY2VJbmRleCA9PT0gJ3N0cmluZycgPyBOdW1iZXIoaW5zdGFuY2VJbmRleC5zcGxpdCgnOicpWzFdKSA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGhvc3QgbmFtZSBvZiBpbnN0YW5jZSBpbmRleFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbnN0YW5jZSBpbmRleFxuICAgKi9cbiAgZ2V0SG9zdE5hbWUoaW5zdGFuY2VJbmRleCkge1xuICAgIHJldHVybiB0eXBlb2YgaW5zdGFuY2VJbmRleCA9PT0gJ3N0cmluZycgPyBpbnN0YW5jZUluZGV4LnNwbGl0KCc6JylbMl0gOiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIGNvbm5lY3Rpb24gdG8gTWV0YVRyYWRlciB0ZXJtaW5hbCBlc3RhYmxpc2hlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge051bWJlcn0gcmVwbGljYXMgbnVtYmVyIG9mIGFjY291bnQgcmVwbGljYXMgbGF1bmNoZWRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvbkNvbm5lY3RlZChpbnN0YW5jZUluZGV4LCByZXBsaWNhcykge31cblxuICAvKipcbiAgICogU2VydmVyLXNpZGUgYXBwbGljYXRpb24gaGVhbHRoIHN0YXR1c1xuICAgKiBAdHlwZWRlZiB7T2JqZWN0fSBoZWFsdGhTdGF0dXNcbiAgICogQHByb3BlcnR5IHtib29sZWFufSBbcmVzdEFwaUhlYWx0aHldIGZsYWcgaW5kaWNhdGluZyB0aGF0IFJFU1QgQVBJIGlzIGhlYWx0aHlcbiAgICogQHByb3BlcnR5IHtib29sZWFufSBbY29weUZhY3RvcnlTdWJzY3JpYmVySGVhbHRoeV0gZmxhZyBpbmRpY2F0aW5nIHRoYXQgQ29weUZhY3Rvcnkgc3Vic2NyaWJlciBpcyBoZWFsdGh5XG4gICAqIEBwcm9wZXJ0eSB7Ym9vbGVhbn0gW2NvcHlGYWN0b3J5UHJvdmlkZXJIZWFsdGh5XSBmbGFnIGluZGljYXRpbmcgdGhhdCBDb3B5RmFjdG9yeSBwcm92aWRlciBpcyBoZWFsdGh5XG4gICAqL1xuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gYSBzZXJ2ZXItc2lkZSBhcHBsaWNhdGlvbiBoZWFsdGggc3RhdHVzIGlzIHJlY2VpdmVkIGZyb20gTWV0YUFwaVxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge0hlYWx0aFN0YXR1c30gc3RhdHVzIHNlcnZlci1zaWRlIGFwcGxpY2F0aW9uIGhlYWx0aCBzdGF0dXNcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvbkhlYWx0aFN0YXR1cyhpbnN0YW5jZUluZGV4LCBzdGF0dXMpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBjb25uZWN0aW9uIHRvIE1ldGFUcmFkZXIgdGVybWluYWwgdGVybWluYXRlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uRGlzY29ubmVjdGVkKGluc3RhbmNlSW5kZXgpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBicm9rZXIgY29ubmVjdGlvbiBzYXR1cyBoYXZlIGNoYW5nZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtCb29sZWFufSBjb25uZWN0ZWQgaXMgTWV0YVRyYWRlciB0ZXJtaW5hbCBpcyBjb25uZWN0ZWQgdG8gYnJva2VyXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25Ccm9rZXJDb25uZWN0aW9uU3RhdHVzQ2hhbmdlZChpbnN0YW5jZUluZGV4LCBjb25uZWN0ZWQpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBNZXRhVHJhZGVyIHRlcm1pbmFsIHN0YXRlIHN5bmNocm9uaXphdGlvbiBpcyBzdGFydGVkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzcGVjaWZpY2F0aW9uc0hhc2ggc3BlY2lmaWNhdGlvbnMgaGFzaFxuICAgKiBAcGFyYW0ge3N0cmluZ30gcG9zaXRpb25zSGFzaCBwb3NpdGlvbnMgaGFzaFxuICAgKiBAcGFyYW0ge3N0cmluZ30gb3JkZXJzSGFzaCBvcmRlcnMgaGFzaFxuICAgKiBAcGFyYW0ge3N0cmluZ30gc3luY2hyb25pemF0aW9uSWQgc3luY2hyb25pemF0aW9uIGlkXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25TeW5jaHJvbml6YXRpb25TdGFydGVkKGluc3RhbmNlSW5kZXgsIHNwZWNpZmljYXRpb25zSGFzaCwgcG9zaXRpb25zSGFzaCwgb3JkZXJzSGFzaCwgc3luY2hyb25pemF0aW9uSWQpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBNZXRhVHJhZGVyIGFjY291bnQgaW5mb3JtYXRpb24gaXMgdXBkYXRlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge01ldGF0cmFkZXJBY2NvdW50SW5mb3JtYXRpb259IGFjY291bnRJbmZvcm1hdGlvbiB1cGRhdGVkIE1ldGFUcmFkZXIgYWNjb3VudCBpbmZvcm1hdGlvblxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uQWNjb3VudEluZm9ybWF0aW9uVXBkYXRlZChpbnN0YW5jZUluZGV4LCBhY2NvdW50SW5mb3JtYXRpb24pIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiB0aGUgcG9zaXRpb25zIGFyZSByZXBsYWNlZCBhcyBhIHJlc3VsdCBvZiBpbml0aWFsIHRlcm1pbmFsIHN0YXRlIHN5bmNocm9uaXphdGlvbi4gVGhpcyBtZXRob2RcbiAgICogd2lsbCBiZSBpbnZva2VkIG9ubHkgaWYgc2VydmVyIHRoaW5rcyB0aGUgZGF0YSB3YXMgdXBkYXRlZCwgb3RoZXJ3aXNlIGludm9jYXRpb24gY2FuIGJlIHNraXBwZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtBcnJheTxNZXRhdHJhZGVyUG9zaXRpb24+fSBwb3NpdGlvbnMgdXBkYXRlZCBhcnJheSBvZiBwb3NpdGlvbnNcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvblBvc2l0aW9uc1JlcGxhY2VkKGluc3RhbmNlSW5kZXgsIHBvc2l0aW9ucykge31cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIHBvc2l0aW9uIHN5bmNocm9uaXphdGlvbiBmbmlzaGVkIHRvIGluZGljYXRlIHByb2dyZXNzIG9mIGFuIGluaXRpYWwgdGVybWluYWwgc3RhdGUgc3luY2hyb25pemF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzeW5jaHJvbml6YXRpb25JZCBzeW5jaHJvbml6YXRpb24gcmVxdWVzdCBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uUG9zaXRpb25zU3luY2hyb25pemVkKGluc3RhbmNlSW5kZXgsIHN5bmNocm9uaXphdGlvbklkKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gTWV0YVRyYWRlciBwb3NpdGlvbnMgYXJlIHVwZGF0ZWRcbiAgICogQHBhcmFtIHtzdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtNZXRhdHJhZGVyUG9zaXRpb25bXX0gcG9zaXRpb25zIHVwZGF0ZWQgTWV0YVRyYWRlciBwb3NpdGlvbnNcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gcmVtb3ZlZFBvc2l0aW9uSWRzIHJlbW92ZWQgcG9zaXRpb24gaWRzXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25Qb3NpdGlvbnNVcGRhdGVkKGluc3RhbmNlSW5kZXgsIHBvc2l0aW9ucywgcmVtb3ZlZFBvc2l0aW9uSWRzKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gTWV0YVRyYWRlciBwb3NpdGlvbiBpcyB1cGRhdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7TWV0YXRyYWRlclBvc2l0aW9ufSBwb3NpdGlvbiB1cGRhdGVkIE1ldGFUcmFkZXIgcG9zaXRpb25cbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvblBvc2l0aW9uVXBkYXRlZChpbnN0YW5jZUluZGV4LCBwb3NpdGlvbikge31cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIE1ldGFUcmFkZXIgcG9zaXRpb24gaXMgcmVtb3ZlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gcG9zaXRpb25JZCByZW1vdmVkIE1ldGFUcmFkZXIgcG9zaXRpb24gaWRcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvblBvc2l0aW9uUmVtb3ZlZChpbnN0YW5jZUluZGV4LCBwb3NpdGlvbklkKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gdGhlIHBlbmRpbmcgb3JkZXJzIGFyZSByZXBsYWNlZCBhcyBhIHJlc3VsdCBvZiBpbml0aWFsIHRlcm1pbmFsIHN0YXRlIHN5bmNocm9uaXphdGlvbi4gVGhpcyBtZXRob2RcbiAgICogd2lsbCBiZSBpbnZva2VkIG9ubHkgaWYgc2VydmVyIHRoaW5rcyB0aGUgZGF0YSB3YXMgdXBkYXRlZCwgb3RoZXJ3aXNlIGludm9jYXRpb24gY2FuIGJlIHNraXBwZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtBcnJheTxNZXRhdHJhZGVyT3JkZXI+fSBvcmRlcnMgdXBkYXRlZCBhcnJheSBvZiBwZW5kaW5nIG9yZGVyc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uUGVuZGluZ09yZGVyc1JlcGxhY2VkKGluc3RhbmNlSW5kZXgsIG9yZGVycykge31cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIE1ldGFUcmFkZXIgcGVuZGluZyBvcmRlcnMgYXJlIHVwZGF0ZWQgb3IgY29tcGxldGVkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7TWV0YXRyYWRlck9yZGVyW119IG9yZGVycyB1cGRhdGVkIE1ldGFUcmFkZXIgcGVuZGluZyBvcmRlcnNcbiAgICogQHBhcmFtIHtzdHJpbmdbXX0gY29tcGxldGVkT3JkZXJJZHMgY29tcGxldGVkIE1ldGFUcmFkZXIgcGVuZGluZyBvcmRlciBpZHNcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvblBlbmRpbmdPcmRlcnNVcGRhdGVkKGluc3RhbmNlSW5kZXgsIG9yZGVycywgY29tcGxldGVkT3JkZXJJZHMpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBNZXRhVHJhZGVyIHBlbmRpbmcgb3JkZXIgaXMgdXBkYXRlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge01ldGF0cmFkZXJPcmRlcn0gb3JkZXIgdXBkYXRlZCBNZXRhVHJhZGVyIHBlbmRpbmcgb3JkZXJcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvblBlbmRpbmdPcmRlclVwZGF0ZWQoaW5zdGFuY2VJbmRleCwgb3JkZXIpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBNZXRhVHJhZGVyIHBlbmRpbmcgb3JkZXIgaXMgY29tcGxldGVkIChleGVjdXRlZCBvciBjYW5jZWxlZClcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IG9yZGVySWQgY29tcGxldGVkIE1ldGFUcmFkZXIgcGVuZGluZyBvcmRlciBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uUGVuZGluZ09yZGVyQ29tcGxldGVkKGluc3RhbmNlSW5kZXgsIG9yZGVySWQpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBwZW5kaW5nIG9yZGVyIHN5bmNocm9uaXphdGlvbiBmbmlzaGVkIHRvIGluZGljYXRlIHByb2dyZXNzIG9mIGFuIGluaXRpYWwgdGVybWluYWwgc3RhdGVcbiAgICogc3luY2hyb25pemF0aW9uXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzeW5jaHJvbml6YXRpb25JZCBzeW5jaHJvbml6YXRpb24gcmVxdWVzdCBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uUGVuZGluZ09yZGVyc1N5bmNocm9uaXplZChpbnN0YW5jZUluZGV4LCBzeW5jaHJvbml6YXRpb25JZCkge31cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIGEgbmV3IE1ldGFUcmFkZXIgaGlzdG9yeSBvcmRlciBpcyBhZGRlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge01ldGF0cmFkZXJPcmRlcn0gaGlzdG9yeU9yZGVyIG5ldyBNZXRhVHJhZGVyIGhpc3Rvcnkgb3JkZXJcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvbkhpc3RvcnlPcmRlckFkZGVkKGluc3RhbmNlSW5kZXgsIGhpc3RvcnlPcmRlcikge31cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIGEgc3luY2hyb25pemF0aW9uIG9mIGhpc3Rvcnkgb3JkZXJzIG9uIGEgTWV0YVRyYWRlciBhY2NvdW50IGhhdmUgZmluaXNoZWQgdG8gaW5kaWNhdGUgcHJvZ3Jlc3Mgb2YgYW5cbiAgICogaW5pdGlhbCB0ZXJtaW5hbCBzdGF0ZSBzeW5jaHJvbml6YXRpb25cbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHN5bmNocm9uaXphdGlvbklkIHN5bmNocm9uaXphdGlvbiByZXF1ZXN0IGlkXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25IaXN0b3J5T3JkZXJzU3luY2hyb25pemVkKGluc3RhbmNlSW5kZXgsIHN5bmNocm9uaXphdGlvbklkKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gYSBuZXcgTWV0YVRyYWRlciBoaXN0b3J5IGRlYWwgaXMgYWRkZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtNZXRhdHJhZGVyRGVhbH0gZGVhbCBuZXcgTWV0YVRyYWRlciBoaXN0b3J5IGRlYWxcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvbkRlYWxBZGRlZChpbnN0YW5jZUluZGV4LCBkZWFsKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gYSBzeW5jaHJvbml6YXRpb24gb2YgaGlzdG9yeSBkZWFscyBvbiBhIE1ldGFUcmFkZXIgYWNjb3VudCBoYXZlIGZpbmlzaGVkIHRvIGluZGljYXRlIHByb2dyZXNzIG9mIGFuXG4gICAqIGluaXRpYWwgdGVybWluYWwgc3RhdGUgc3luY2hyb25pemF0aW9uXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBzeW5jaHJvbml6YXRpb25JZCBzeW5jaHJvbml6YXRpb24gcmVxdWVzdCBpZFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uRGVhbHNTeW5jaHJvbml6ZWQoaW5zdGFuY2VJbmRleCwgc3luY2hyb25pemF0aW9uSWQpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBhIHN5bWJvbCBzcGVjaWZpY2F0aW9uIHdhcyB1cGRhdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7TWV0YXRyYWRlclN5bWJvbFNwZWNpZmljYXRpb259IHNwZWNpZmljYXRpb24gdXBkYXRlZCBNZXRhVHJhZGVyIHN5bWJvbCBzcGVjaWZpY2F0aW9uXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25TeW1ib2xTcGVjaWZpY2F0aW9uVXBkYXRlZChpbnN0YW5jZUluZGV4LCBzcGVjaWZpY2F0aW9uKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gYSBzeW1ib2wgc3BlY2lmaWNhdGlvbiB3YXMgcmVtb3ZlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gc3ltYm9sIHJlbW92ZWQgc3ltYm9sXG4gICAqIEByZXR1cm5zIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uU3ltYm9sU3BlY2lmaWNhdGlvblJlbW92ZWQoaW5zdGFuY2VJbmRleCwgc3ltYm9sKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gYSBzeW1ib2wgc3BlY2lmaWNhdGlvbnMgd2VyZSB1cGRhdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7QXJyYXk8TWV0YXRyYWRlclN5bWJvbFNwZWNpZmljYXRpb24+fSBzcGVjaWZpY2F0aW9ucyB1cGRhdGVkIHNwZWNpZmljYXRpb25zXG4gICAqIEBwYXJhbSB7QXJyYXk8U3RyaW5nPn0gcmVtb3ZlZFN5bWJvbHMgcmVtb3ZlZCBzeW1ib2xzXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25TeW1ib2xTcGVjaWZpY2F0aW9uc1VwZGF0ZWQoaW5zdGFuY2VJbmRleCwgc3BlY2lmaWNhdGlvbnMsIHJlbW92ZWRTeW1ib2xzKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gYSBzeW1ib2wgcHJpY2Ugd2FzIHVwZGF0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtNZXRhdHJhZGVyU3ltYm9sUHJpY2V9IHByaWNlIHVwZGF0ZWQgTWV0YVRyYWRlciBzeW1ib2wgcHJpY2VcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvblN5bWJvbFByaWNlVXBkYXRlZChpbnN0YW5jZUluZGV4LCBwcmljZSkge31cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIHByaWNlcyBmb3Igc2V2ZXJhbCBzeW1ib2xzIHdlcmUgdXBkYXRlZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaW5zdGFuY2VJbmRleCBpbmRleCBvZiBhbiBhY2NvdW50IGluc3RhbmNlIGNvbm5lY3RlZFxuICAgKiBAcGFyYW0ge0FycmF5PE1ldGF0cmFkZXJTeW1ib2xQcmljZT59IHByaWNlcyB1cGRhdGVkIE1ldGFUcmFkZXIgc3ltYm9sIHByaWNlc1xuICAgKiBAcGFyYW0ge051bWJlcn0gZXF1aXR5IGFjY291bnQgbGlxdWlkYXRpb24gdmFsdWVcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG1hcmdpbiBtYXJnaW4gdXNlZFxuICAgKiBAcGFyYW0ge051bWJlcn0gZnJlZU1hcmdpbiBmcmVlIG1hcmdpblxuICAgKiBAcGFyYW0ge051bWJlcn0gbWFyZ2luTGV2ZWwgbWFyZ2luIGxldmVsIGNhbGN1bGF0ZWQgYXMgJSBvZiBlcXVpdHkvbWFyZ2luXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBhY2NvdW50Q3VycmVuY3lFeGNoYW5nZVJhdGUgY3VycmVudCBleGNoYW5nZSByYXRlIG9mIGFjY291bnQgY3VycmVuY3kgaW50byBVU0RcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvblN5bWJvbFByaWNlc1VwZGF0ZWQoaW5zdGFuY2VJbmRleCwgcHJpY2VzLCBlcXVpdHksIG1hcmdpbiwgZnJlZU1hcmdpbiwgbWFyZ2luTGV2ZWwsXG4gICAgYWNjb3VudEN1cnJlbmN5RXhjaGFuZ2VSYXRlKSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gc3ltYm9sIGNhbmRsZXMgd2VyZSB1cGRhdGVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7QXJyYXk8TWV0YXRyYWRlckNhbmRsZT59IGNhbmRsZXMgdXBkYXRlZCBNZXRhVHJhZGVyIHN5bWJvbCBjYW5kbGVzXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBlcXVpdHkgYWNjb3VudCBsaXF1aWRhdGlvbiB2YWx1ZVxuICAgKiBAcGFyYW0ge051bWJlcn0gbWFyZ2luIG1hcmdpbiB1c2VkXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBmcmVlTWFyZ2luIGZyZWUgbWFyZ2luXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBtYXJnaW5MZXZlbCBtYXJnaW4gbGV2ZWwgY2FsY3VsYXRlZCBhcyAlIG9mIGVxdWl0eS9tYXJnaW5cbiAgICogQHBhcmFtIHtOdW1iZXJ9IGFjY291bnRDdXJyZW5jeUV4Y2hhbmdlUmF0ZSBjdXJyZW50IGV4Y2hhbmdlIHJhdGUgb2YgYWNjb3VudCBjdXJyZW5jeSBpbnRvIFVTRFxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHdoaWNoIHJlc29sdmVzIHdoZW4gdGhlIGFzeW5jaHJvbm91cyBldmVudCBpcyBwcm9jZXNzZWRcbiAgICovXG4gIGFzeW5jIG9uQ2FuZGxlc1VwZGF0ZWQoaW5zdGFuY2VJbmRleCwgY2FuZGxlcywgZXF1aXR5LCBtYXJnaW4sIGZyZWVNYXJnaW4sIG1hcmdpbkxldmVsLFxuICAgIGFjY291bnRDdXJyZW5jeUV4Y2hhbmdlUmF0ZSkge31cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIHN5bWJvbCB0aWNrcyB3ZXJlIHVwZGF0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtBcnJheTxNZXRhdHJhZGVyVGljaz59IHRpY2tzIHVwZGF0ZWQgTWV0YVRyYWRlciBzeW1ib2wgdGlja3NcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGVxdWl0eSBhY2NvdW50IGxpcXVpZGF0aW9uIHZhbHVlXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBtYXJnaW4gbWFyZ2luIHVzZWRcbiAgICogQHBhcmFtIHtOdW1iZXJ9IGZyZWVNYXJnaW4gZnJlZSBtYXJnaW5cbiAgICogQHBhcmFtIHtOdW1iZXJ9IG1hcmdpbkxldmVsIG1hcmdpbiBsZXZlbCBjYWxjdWxhdGVkIGFzICUgb2YgZXF1aXR5L21hcmdpblxuICAgKiBAcGFyYW0ge051bWJlcn0gYWNjb3VudEN1cnJlbmN5RXhjaGFuZ2VSYXRlIGN1cnJlbnQgZXhjaGFuZ2UgcmF0ZSBvZiBhY2NvdW50IGN1cnJlbmN5IGludG8gVVNEXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25UaWNrc1VwZGF0ZWQoaW5zdGFuY2VJbmRleCwgdGlja3MsIGVxdWl0eSwgbWFyZ2luLCBmcmVlTWFyZ2luLCBtYXJnaW5MZXZlbCxcbiAgICBhY2NvdW50Q3VycmVuY3lFeGNoYW5nZVJhdGUpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBvcmRlciBib29rcyB3ZXJlIHVwZGF0ZWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGluc3RhbmNlSW5kZXggaW5kZXggb2YgYW4gYWNjb3VudCBpbnN0YW5jZSBjb25uZWN0ZWRcbiAgICogQHBhcmFtIHtBcnJheTxNZXRhdHJhZGVyQm9vaz59IGJvb2tzIHVwZGF0ZWQgTWV0YVRyYWRlciBvcmRlciBib29rc1xuICAgKiBAcGFyYW0ge051bWJlcn0gZXF1aXR5IGFjY291bnQgbGlxdWlkYXRpb24gdmFsdWVcbiAgICogQHBhcmFtIHtOdW1iZXJ9IG1hcmdpbiBtYXJnaW4gdXNlZFxuICAgKiBAcGFyYW0ge051bWJlcn0gZnJlZU1hcmdpbiBmcmVlIG1hcmdpblxuICAgKiBAcGFyYW0ge051bWJlcn0gbWFyZ2luTGV2ZWwgbWFyZ2luIGxldmVsIGNhbGN1bGF0ZWQgYXMgJSBvZiBlcXVpdHkvbWFyZ2luXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBhY2NvdW50Q3VycmVuY3lFeGNoYW5nZVJhdGUgY3VycmVudCBleGNoYW5nZSByYXRlIG9mIGFjY291bnQgY3VycmVuY3kgaW50byBVU0RcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvbkJvb2tzVXBkYXRlZChpbnN0YW5jZUluZGV4LCBib29rcywgZXF1aXR5LCBtYXJnaW4sIGZyZWVNYXJnaW4sIG1hcmdpbkxldmVsLFxuICAgIGFjY291bnRDdXJyZW5jeUV4Y2hhbmdlUmF0ZSkge31cblxuICAvKipcbiAgICogSW52b2tlZCB3aGVuIHN1YnNjcmlwdGlvbiBkb3duZ3JhZGUgaGFzIG9jY3VycmVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBzeW1ib2wgc3ltYm9sIHRvIHVwZGF0ZSBzdWJzY3JpcHRpb25zIGZvclxuICAgKiBAcGFyYW0ge0FycmF5PE1hcmtldERhdGFTdWJzY3JpcHRpb24+fSB1cGRhdGVzIGFycmF5IG9mIG1hcmtldCBkYXRhIHN1YnNjcmlwdGlvbiB0byB1cGRhdGVcbiAgICogQHBhcmFtIHtBcnJheTxNYXJrZXREYXRhVW5zdWJzY3JpcHRpb24+fSB1bnN1YnNjcmlwdGlvbnMgYXJyYXkgb2Ygc3Vic2NyaXB0aW9ucyB0byBjYW5jZWxcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSB3aGljaCByZXNvbHZlcyB3aGVuIHRoZSBhc3luY2hyb25vdXMgZXZlbnQgaXMgcHJvY2Vzc2VkXG4gICAqL1xuICBhc3luYyBvblN1YnNjcmlwdGlvbkRvd25ncmFkZWQoaW5zdGFuY2VJbmRleCwgc3ltYm9sLCB1cGRhdGVzLCB1bnN1YnNjcmlwdGlvbnMpIHt9XG5cbiAgLyoqXG4gICAqIEludm9rZWQgd2hlbiBhIHN0cmVhbSBmb3IgYW4gaW5zdGFuY2UgaW5kZXggaXMgY2xvc2VkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpbnN0YW5jZUluZGV4IGluZGV4IG9mIGFuIGFjY291bnQgaW5zdGFuY2UgY29ubmVjdGVkXG4gICAqL1xuICBhc3luYyBvblN0cmVhbUNsb3NlZChpbnN0YW5jZUluZGV4KSB7fVxuXG4gIC8qKlxuICAgKiBJbnZva2VkIHdoZW4gYWNjb3VudCByZWdpb24gaGFzIGJlZW4gdW5zdWJzY3JpYmVkXG4gICAqIEBwYXJhbSB7U3RyaW5nfSByZWdpb24gYWNjb3VudCByZWdpb24gdW5zdWJzY3JpYmVkXG4gICAqIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2Ugd2hpY2ggcmVzb2x2ZXMgd2hlbiB0aGUgYXN5bmNocm9ub3VzIGV2ZW50IGlzIHByb2Nlc3NlZFxuICAgKi9cbiAgYXN5bmMgb25VbnN1YnNjcmliZVJlZ2lvbihyZWdpb24pIHt9XG5cbn1cbiJdLCJuYW1lcyI6WyJTeW5jaHJvbml6YXRpb25MaXN0ZW5lciIsImdldFJlZ2lvbiIsImluc3RhbmNlSW5kZXgiLCJzcGxpdCIsInVuZGVmaW5lZCIsImdldEluc3RhbmNlTnVtYmVyIiwiTnVtYmVyIiwiZ2V0SG9zdE5hbWUiLCJvbkNvbm5lY3RlZCIsInJlcGxpY2FzIiwib25IZWFsdGhTdGF0dXMiLCJzdGF0dXMiLCJvbkRpc2Nvbm5lY3RlZCIsIm9uQnJva2VyQ29ubmVjdGlvblN0YXR1c0NoYW5nZWQiLCJjb25uZWN0ZWQiLCJvblN5bmNocm9uaXphdGlvblN0YXJ0ZWQiLCJzcGVjaWZpY2F0aW9uc0hhc2giLCJwb3NpdGlvbnNIYXNoIiwib3JkZXJzSGFzaCIsInN5bmNocm9uaXphdGlvbklkIiwib25BY2NvdW50SW5mb3JtYXRpb25VcGRhdGVkIiwiYWNjb3VudEluZm9ybWF0aW9uIiwib25Qb3NpdGlvbnNSZXBsYWNlZCIsInBvc2l0aW9ucyIsIm9uUG9zaXRpb25zU3luY2hyb25pemVkIiwib25Qb3NpdGlvbnNVcGRhdGVkIiwicmVtb3ZlZFBvc2l0aW9uSWRzIiwib25Qb3NpdGlvblVwZGF0ZWQiLCJwb3NpdGlvbiIsIm9uUG9zaXRpb25SZW1vdmVkIiwicG9zaXRpb25JZCIsIm9uUGVuZGluZ09yZGVyc1JlcGxhY2VkIiwib3JkZXJzIiwib25QZW5kaW5nT3JkZXJzVXBkYXRlZCIsImNvbXBsZXRlZE9yZGVySWRzIiwib25QZW5kaW5nT3JkZXJVcGRhdGVkIiwib3JkZXIiLCJvblBlbmRpbmdPcmRlckNvbXBsZXRlZCIsIm9yZGVySWQiLCJvblBlbmRpbmdPcmRlcnNTeW5jaHJvbml6ZWQiLCJvbkhpc3RvcnlPcmRlckFkZGVkIiwiaGlzdG9yeU9yZGVyIiwib25IaXN0b3J5T3JkZXJzU3luY2hyb25pemVkIiwib25EZWFsQWRkZWQiLCJkZWFsIiwib25EZWFsc1N5bmNocm9uaXplZCIsIm9uU3ltYm9sU3BlY2lmaWNhdGlvblVwZGF0ZWQiLCJzcGVjaWZpY2F0aW9uIiwib25TeW1ib2xTcGVjaWZpY2F0aW9uUmVtb3ZlZCIsInN5bWJvbCIsIm9uU3ltYm9sU3BlY2lmaWNhdGlvbnNVcGRhdGVkIiwic3BlY2lmaWNhdGlvbnMiLCJyZW1vdmVkU3ltYm9scyIsIm9uU3ltYm9sUHJpY2VVcGRhdGVkIiwicHJpY2UiLCJvblN5bWJvbFByaWNlc1VwZGF0ZWQiLCJwcmljZXMiLCJlcXVpdHkiLCJtYXJnaW4iLCJmcmVlTWFyZ2luIiwibWFyZ2luTGV2ZWwiLCJhY2NvdW50Q3VycmVuY3lFeGNoYW5nZVJhdGUiLCJvbkNhbmRsZXNVcGRhdGVkIiwiY2FuZGxlcyIsIm9uVGlja3NVcGRhdGVkIiwidGlja3MiLCJvbkJvb2tzVXBkYXRlZCIsImJvb2tzIiwib25TdWJzY3JpcHRpb25Eb3duZ3JhZGVkIiwidXBkYXRlcyIsInVuc3Vic2NyaXB0aW9ucyIsIm9uU3RyZWFtQ2xvc2VkIiwib25VbnN1YnNjcmliZVJlZ2lvbiIsInJlZ2lvbiJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7ZUFLcUJBOzs7QUFBTixJQUFBLEFBQU1BLDBCQUFOLE1BQU1BO0lBRW5COzs7R0FHQyxHQUNEQyxVQUFVQyxhQUFhLEVBQUU7UUFDdkIsT0FBTyxPQUFPQSxrQkFBa0IsV0FBV0EsY0FBY0MsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUdDO0lBQzNFO0lBRUE7OztHQUdDLEdBQ0RDLGtCQUFrQkgsYUFBYSxFQUFFO1FBQy9CLE9BQU8sT0FBT0Esa0JBQWtCLFdBQVdJLE9BQU9KLGNBQWNDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJQztJQUNuRjtJQUVBOzs7R0FHQyxHQUNERyxZQUFZTCxhQUFhLEVBQUU7UUFDekIsT0FBTyxPQUFPQSxrQkFBa0IsV0FBV0EsY0FBY0MsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUdDO0lBQzNFO0lBRUE7Ozs7O0dBS0MsR0FDRCxNQUFNSSxZQUFZTixhQUFh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