UNPKG

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)

285 lines (284 loc) 37 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "default", { enumerable: true, get: function() { return EquityTrackingClient; } }); const _trackerEventListenerManager = /*#__PURE__*/ _interop_require_default(require("./trackerEventListenerManager")); const _periodStatisticsStreamManager = /*#__PURE__*/ _interop_require_default(require("./periodStatisticsStreamManager")); const _equityChartStreamManager = /*#__PURE__*/ _interop_require_default(require("./equityChartStreamManager")); const _equityBalanceStreamManager = /*#__PURE__*/ _interop_require_default(require("./equityBalanceStreamManager")); const _moment = /*#__PURE__*/ _interop_require_default(require("moment")); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } let EquityTrackingClient = class EquityTrackingClient { /** * Creates a profit/drawdown tracker. See * https://metaapi.cloud/docs/risk-management/restApi/api/createTracker/ * @param {String} accountId id of the MetaApi account * @param {NewTracker} tracker profit/drawdown tracker * @return {Promise<TrackerId>} promise resolving with profit/drawdown tracker id */ createTracker(accountId, tracker) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers`, headers: { "auth-token": this._domainClient.token, "api-version": "1" }, method: "POST", data: tracker }); } /** * Returns trackers defined for an account. See * https://metaapi.cloud/docs/risk-management/restApi/api/getTrackers/ * @param {String} accountId id of the MetaApi account * @return {Promise<Tracker[]>} promise resolving with trackers */ getTrackers(accountId) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers`, headers: { "auth-token": this._domainClient.token, "api-version": "1" }, method: "GET" }); } /** * Returns profit/drawdown tracker by account and id. See * https://metaapi.cloud/docs/risk-management/restApi/api/getTracker/ * @param {string} accountId id of the MetaApi account * @param {string} id tracker id * @returns {Promise<Tracker>} promise resolving with profit/drawdown tracker found */ getTracker(accountId, id) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/${id}`, headers: { "auth-token": this._domainClient.token, "api-version": "1" }, method: "GET" }); } /** * Returns profit/drawdown tracker by account and name * @param {string} accountId id of the MetaApi account * @param {string} name tracker name * @returns {Promise<Tracker>} promise resolving with profit/drawdown tracker found */ getTrackerByName(accountId, name) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/name/${encodeURIComponent(name)}`, headers: { "auth-token": this._domainClient.token, "api-version": "1" }, method: "GET" }); } /** * Updates profit/drawdown tracker. See * https://metaapi.cloud/docs/risk-management/restApi/api/updateTracker/ * @param {String} accountId id of the MetaApi account * @param {String} id id of the tracker * @param {TrackerUpdate} update tracker update * @return {Promise} promise resolving when profit/drawdown tracker updated */ updateTracker(accountId, id, update) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/${id}`, method: "PUT", data: update }); } /** * Removes profit/drawdown tracker. See * https://metaapi.cloud/docs/risk-management/restApi/api/removeTracker/ * @param {String} accountId id of the MetaApi account * @param {String} id id of the tracker * @return {Promise} promise resolving when profit/drawdown tracker removed */ deleteTracker(accountId, id) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/${id}`, method: "DELETE" }); } /** * Returns tracker events by broker time range. See * https://metaapi.cloud/docs/risk-management/restApi/api/getTrackerEvents/ * @param {String} [startBrokerTime] value of the event time in broker timezone to start loading data from, inclusive, * in 'YYYY-MM-DD HH:mm:ss.SSS format * @param {String} [endBrokerTime] value of the event time in broker timezone to end loading data at, inclusive, * in 'YYYY-MM-DD HH:mm:ss.SSS format * @param {String} [accountId] id of the MetaApi account * @param {String} [trackerId] id of the tracker * @param {Number} [limit] pagination limit, default is 1000 * @return {Promise<TrackerEvent[]>} promise resolving with tracker events */ getTrackerEvents(startBrokerTime, endBrokerTime, accountId, trackerId, limit) { return this._domainClient.requestApi({ url: "/users/current/tracker-events/by-broker-time", params: { startBrokerTime, endBrokerTime, accountId, trackerId, limit }, method: "GET" }); } /** * Adds a tracker event listener and creates a job to make requests * @param {TrackerEventListener} listener tracker event listener * @param {String} [accountId] account id * @param {String} [trackerId] tracker id * @param {Number} [sequenceNumber] sequence number * @return {String} listener id */ addTrackerEventListener(listener, accountId, trackerId, sequenceNumber) { return this._trackerEventListenerManager.addTrackerEventListener(listener, accountId, trackerId, sequenceNumber); } /** * Removes tracker event listener and cancels the event stream * @param {String} listenerId tracker event listener id */ removeTrackerEventListener(listenerId) { this._trackerEventListenerManager.removeTrackerEventListener(listenerId); } /** * Returns account profit and drawdown tracking statistics by tracker id. See * https://metaapi.cloud/docs/risk-management/restApi/api/getTrackingStats/ * @param {String} accountId id of MetaAPI account * @param {String} trackerId id of the tracker * @param {String} [startTime] time to start loading stats from, default is current time. Note that stats is loaded in * backwards direction * @param {Number} [limit] number of records to load, default is 1 * @param {Boolean} [realTime] if true, real-time data will be requested * @return {Promise<PeriodStatistics[]>} promise resolving with profit and drawdown statistics */ getTrackingStatistics(accountId, trackerId, startTime, limit, realTime = false) { return this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/trackers/${trackerId}/statistics`, headers: { "auth-token": this._domainClient.token, "api-version": "1" }, params: { startTime, limit, realTime }, method: "GET" }); } /** * Adds a period statistics event listener * @param {PeriodStatisticsListener} listener period statistics event listener * @param {String} accountId account id * @param {String} trackerId tracker id * @returns {Promise<String>} listener id */ addPeriodStatisticsListener(listener, accountId, trackerId) { return this._periodStatisticsStreamManager.addPeriodStatisticsListener(listener, accountId, trackerId); } /** * Removes period statistics event listener by id * @param {String} listenerId listener id */ removePeriodStatisticsListener(listenerId) { this._periodStatisticsStreamManager.removePeriodStatisticsListener(listenerId); } /** * Returns equity chart by account id. See * https://metaapi.cloud/docs/risk-management/restApi/api/getEquityChart/ * @param {String} accountId metaApi account id * @param {String} [startTime] starting broker time in YYYY-MM-DD HH:mm:ss format * @param {String} [endTime] ending broker time in YYYY-MM-DD HH:mm:ss format * @param {Boolean} [realTime] if true, real-time data will be requested * @param {Boolean} [fillSkips] if true, skipped records will be automatically filled based on existing ones * @return {Promise<EquityChartItem[]>} promise resolving with equity chart */ async getEquityChart(accountId, startTime, endTime, realTime = false, fillSkips = false) { const records = await this._domainClient.requestApi({ url: `/users/current/accounts/${accountId}/equity-chart`, headers: { "auth-token": this._domainClient.token, "api-version": "1" }, params: { startTime, endTime, realTime }, method: "GET" }); if (fillSkips) { let i = 0; while(i < records.length - 1){ const timeDiff = new Date(records[i + 1].startBrokerTime).getTime() - new Date(records[i].startBrokerTime).getTime(); if (timeDiff > 60 * 60 * 1000 && records[i].lastBalance !== undefined) { const recordCopy = JSON.parse(JSON.stringify(records[i])); recordCopy.minEquity = recordCopy.lastEquity; recordCopy.maxEquity = recordCopy.lastEquity; recordCopy.averageEquity = recordCopy.lastEquity; recordCopy.minBalance = recordCopy.lastBalance; recordCopy.maxBalance = recordCopy.lastBalance; recordCopy.averageBalance = recordCopy.lastBalance; const startBrokerTime = new Date(recordCopy.startBrokerTime); startBrokerTime.setUTCHours(startBrokerTime.getUTCHours() + 1); startBrokerTime.setUTCMinutes(0); startBrokerTime.setUTCSeconds(0); startBrokerTime.setUTCMilliseconds(0); recordCopy.startBrokerTime = (0, _moment.default)(startBrokerTime).format("YYYY-MM-DD HH:mm:ss.SSS"); startBrokerTime.setUTCHours(startBrokerTime.getUTCHours() + 1); startBrokerTime.setUTCMilliseconds(-1); recordCopy.endBrokerTime = (0, _moment.default)(startBrokerTime).format("YYYY-MM-DD HH:mm:ss.SSS"); recordCopy.brokerTime = recordCopy.endBrokerTime; records.splice(i + 1, 0, recordCopy); } i++; } } return records; } /** * Adds an equity chart event listener * @param {EquityChartListener} listener equity chart event listener * @param {String} accountId account id * @param {Date} [startTime] date to start tracking from * @returns {Promise<string>} listener id */ addEquityChartListener(listener, accountId, startTime) { return this._equityChartStreamManager.addEquityChartListener(listener, accountId, startTime); } /** * Removes equity chart event listener by id * @param {String} listenerId equity chart listener id */ removeEquityChartListener(listenerId) { this._equityChartStreamManager.removeEquityChartListener(listenerId); } /** * Adds an equity balance event listener * @param {EquityBalanceListener} listener equity balance event listener * @param {string} accountId account id * @returns {Promise<string>} listener id */ addEquityBalanceListener(listener, accountId) { return this._equityBalanceStreamManager.addEquityBalanceListener(listener, accountId); } /** * Removes equity balance event listener by id * @param {string} listenerId equity balance listener id */ removeEquityBalanceListener(listenerId) { this._equityBalanceStreamManager.removeEquityBalanceListener(listenerId); } /** * Constructs RiskManagement equity tracking API client instance * @param {DomainClient} domainClient domain client * @param {MetaApi} metaApi metaApi SDK instance */ constructor(domainClient, metaApi){ this._domainClient = domainClient; this._trackerEventListenerManager = new _trackerEventListenerManager.default(domainClient); this._equityBalanceStreamManager = new _equityBalanceStreamManager.default(domainClient, metaApi); this._periodStatisticsStreamManager = new _periodStatisticsStreamManager.default(domainClient, this, metaApi); this._equityChartStreamManager = new _equityChartStreamManager.default(domainClient, this, metaApi); } }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBUcmFja2VyRXZlbnRMaXN0ZW5lck1hbmFnZXIgZnJvbSAnLi90cmFja2VyRXZlbnRMaXN0ZW5lck1hbmFnZXInO1xuaW1wb3J0IFBlcmlvZFN0YXRpc3RpY3NTdHJlYW1NYW5hZ2VyIGZyb20gJy4vcGVyaW9kU3RhdGlzdGljc1N0cmVhbU1hbmFnZXInO1xuaW1wb3J0IEVxdWl0eUNoYXJ0U3RyZWFtTWFuYWdlciBmcm9tICcuL2VxdWl0eUNoYXJ0U3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgRXF1aXR5QmFsYW5jZVN0cmVhbU1hbmFnZXIgZnJvbSAnLi9lcXVpdHlCYWxhbmNlU3RyZWFtTWFuYWdlcic7XG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5cbi8qKlxuICogbWV0YWFwaS5jbG91ZCBSaXNrTWFuYWdlbWVudCBlcXVpdHkgdHJhY2tpbmcgQVBJIGNsaWVudCAoc2VlIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Jpc2stbWFuYWdlbWVudC8pXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEVxdWl0eVRyYWNraW5nQ2xpZW50IHtcblxuICAvKipcbiAgICogQ29uc3RydWN0cyBSaXNrTWFuYWdlbWVudCBlcXVpdHkgdHJhY2tpbmcgQVBJIGNsaWVudCBpbnN0YW5jZVxuICAgKiBAcGFyYW0ge0RvbWFpbkNsaWVudH0gZG9tYWluQ2xpZW50IGRvbWFpbiBjbGllbnRcbiAgICogQHBhcmFtIHtNZXRhQXBpfSBtZXRhQXBpIG1ldGFBcGkgU0RLIGluc3RhbmNlXG4gICAqL1xuICBjb25zdHJ1Y3Rvcihkb21haW5DbGllbnQsIG1ldGFBcGkpIHtcbiAgICB0aGlzLl9kb21haW5DbGllbnQgPSBkb21haW5DbGllbnQ7XG4gICAgdGhpcy5fdHJhY2tlckV2ZW50TGlzdGVuZXJNYW5hZ2VyID0gbmV3IFRyYWNrZXJFdmVudExpc3RlbmVyTWFuYWdlcihkb21haW5DbGllbnQpO1xuICAgIHRoaXMuX2VxdWl0eUJhbGFuY2VTdHJlYW1NYW5hZ2VyID0gbmV3IEVxdWl0eUJhbGFuY2VTdHJlYW1NYW5hZ2VyKGRvbWFpbkNsaWVudCwgbWV0YUFwaSk7XG4gICAgdGhpcy5fcGVyaW9kU3RhdGlzdGljc1N0cmVhbU1hbmFnZXIgPSBuZXcgUGVyaW9kU3RhdGlzdGljc1N0cmVhbU1hbmFnZXIoZG9tYWluQ2xpZW50LCB0aGlzLCBtZXRhQXBpKTtcbiAgICB0aGlzLl9lcXVpdHlDaGFydFN0cmVhbU1hbmFnZXIgPSBuZXcgRXF1aXR5Q2hhcnRTdHJlYW1NYW5hZ2VyKGRvbWFpbkNsaWVudCwgdGhpcywgbWV0YUFwaSk7IFxuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYSBwcm9maXQvZHJhd2Rvd24gdHJhY2tlci4gU2VlXG4gICAqIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Jpc2stbWFuYWdlbWVudC9yZXN0QXBpL2FwaS9jcmVhdGVUcmFja2VyL1xuICAgKiBAcGFyYW0ge1N0cmluZ30gYWNjb3VudElkIGlkIG9mIHRoZSBNZXRhQXBpIGFjY291bnRcbiAgICogQHBhcmFtIHtOZXdUcmFja2VyfSB0cmFja2VyIHByb2ZpdC9kcmF3ZG93biB0cmFja2VyXG4gICAqIEByZXR1cm4ge1Byb21pc2U8VHJhY2tlcklkPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCBwcm9maXQvZHJhd2Rvd24gdHJhY2tlciBpZFxuICAgKi9cbiAgY3JlYXRlVHJhY2tlcihhY2NvdW50SWQsIHRyYWNrZXIpIHtcbiAgICByZXR1cm4gdGhpcy5fZG9tYWluQ2xpZW50LnJlcXVlc3RBcGkoe1xuICAgICAgdXJsOiBgL3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHthY2NvdW50SWR9L3RyYWNrZXJzYCxcbiAgICAgIGhlYWRlcnM6IHsnYXV0aC10b2tlbic6IHRoaXMuX2RvbWFpbkNsaWVudC50b2tlbiwgJ2FwaS12ZXJzaW9uJzogJzEnfSxcbiAgICAgIG1ldGhvZDogJ1BPU1QnLFxuICAgICAgZGF0YTogdHJhY2tlclxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJhY2tlcnMgZGVmaW5lZCBmb3IgYW4gYWNjb3VudC4gU2VlXG4gICAqIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Jpc2stbWFuYWdlbWVudC9yZXN0QXBpL2FwaS9nZXRUcmFja2Vycy9cbiAgICogQHBhcmFtIHtTdHJpbmd9IGFjY291bnRJZCBpZCBvZiB0aGUgTWV0YUFwaSBhY2NvdW50XG4gICAqIEByZXR1cm4ge1Byb21pc2U8VHJhY2tlcltdPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCB0cmFja2Vyc1xuICAgKi9cbiAgZ2V0VHJhY2tlcnMoYWNjb3VudElkKSB7XG4gICAgcmV0dXJuIHRoaXMuX2RvbWFpbkNsaWVudC5yZXF1ZXN0QXBpKHtcbiAgICAgIHVybDogYC91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7YWNjb3VudElkfS90cmFja2Vyc2AsXG4gICAgICBoZWFkZXJzOiB7J2F1dGgtdG9rZW4nOiB0aGlzLl9kb21haW5DbGllbnQudG9rZW4sICdhcGktdmVyc2lvbic6ICcxJ30sXG4gICAgICBtZXRob2Q6ICdHRVQnXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBwcm9maXQvZHJhd2Rvd24gdHJhY2tlciBieSBhY2NvdW50IGFuZCBpZC4gU2VlXG4gICAqIGh0dHBzOi8vbWV0YWFwaS5jbG91ZC9kb2NzL3Jpc2stbWFuYWdlbWVudC9yZXN0QXBpL2FwaS9nZXRUcmFja2VyL1xuICAgKiBAcGFyYW0ge3N0cmluZ30gYWNjb3VudElkIGlkIG9mIHRoZSBNZXRhQXBpIGFjY291bnQgXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBpZCB0cmFja2VyIGlkIFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUcmFja2VyPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCBwcm9maXQvZHJhd2Rvd24gdHJhY2tlciBmb3VuZFxuICAgKi9cbiAgZ2V0VHJhY2tlcihhY2NvdW50SWQsIGlkKSB7XG4gICAgcmV0dXJuIHRoaXMuX2RvbWFpbkNsaWVudC5yZXF1ZXN0QXBpKHtcbiAgICAgIHVybDogYC91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7YWNjb3VudElkfS90cmFja2Vycy8ke2lkfWAsXG4gICAgICBoZWFkZXJzOiB7J2F1dGgtdG9rZW4nOiB0aGlzLl9kb21haW5DbGllbnQudG9rZW4sICdhcGktdmVyc2lvbic6ICcxJ30sXG4gICAgICBtZXRob2Q6ICdHRVQnXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBwcm9maXQvZHJhd2Rvd24gdHJhY2tlciBieSBhY2NvdW50IGFuZCBuYW1lXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBhY2NvdW50SWQgaWQgb2YgdGhlIE1ldGFBcGkgYWNjb3VudCBcbiAgICogQHBhcmFtIHtzdHJpbmd9IG5hbWUgdHJhY2tlciBuYW1lIFxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxUcmFja2VyPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCBwcm9maXQvZHJhd2Rvd24gdHJhY2tlciBmb3VuZFxuICAgKi9cbiAgZ2V0VHJhY2tlckJ5TmFtZShhY2NvdW50SWQsIG5hbWUpIHtcbiAgICByZXR1cm4gdGhpcy5fZG9tYWluQ2xpZW50LnJlcXVlc3RBcGkoe1xuICAgICAgdXJsOiBgL3VzZXJzL2N1cnJlbnQvYWNjb3VudHMvJHthY2NvdW50SWR9L3RyYWNrZXJzL25hbWUvJHtlbmNvZGVVUklDb21wb25lbnQobmFtZSl9YCxcbiAgICAgIGhlYWRlcnM6IHsnYXV0aC10b2tlbic6IHRoaXMuX2RvbWFpbkNsaWVudC50b2tlbiwgJ2FwaS12ZXJzaW9uJzogJzEnfSxcbiAgICAgIG1ldGhvZDogJ0dFVCdcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHByb2ZpdC9kcmF3ZG93biB0cmFja2VyLiBTZWVcbiAgICogaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3Mvcmlzay1tYW5hZ2VtZW50L3Jlc3RBcGkvYXBpL3VwZGF0ZVRyYWNrZXIvXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBhY2NvdW50SWQgaWQgb2YgdGhlIE1ldGFBcGkgYWNjb3VudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gaWQgaWQgb2YgdGhlIHRyYWNrZXJcbiAgICogQHBhcmFtIHtUcmFja2VyVXBkYXRlfSB1cGRhdGUgdHJhY2tlciB1cGRhdGVcbiAgICogQHJldHVybiB7UHJvbWlzZX0gcHJvbWlzZSByZXNvbHZpbmcgd2hlbiBwcm9maXQvZHJhd2Rvd24gdHJhY2tlciB1cGRhdGVkXG4gICAqL1xuICB1cGRhdGVUcmFja2VyKGFjY291bnRJZCwgaWQsIHVwZGF0ZSkge1xuICAgIHJldHVybiB0aGlzLl9kb21haW5DbGllbnQucmVxdWVzdEFwaSh7XG4gICAgICB1cmw6IGAvdXNlcnMvY3VycmVudC9hY2NvdW50cy8ke2FjY291bnRJZH0vdHJhY2tlcnMvJHtpZH1gLFxuICAgICAgbWV0aG9kOiAnUFVUJyxcbiAgICAgIGRhdGE6IHVwZGF0ZVxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgcHJvZml0L2RyYXdkb3duIHRyYWNrZXIuIFNlZVxuICAgKiBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9yaXNrLW1hbmFnZW1lbnQvcmVzdEFwaS9hcGkvcmVtb3ZlVHJhY2tlci9cbiAgICogQHBhcmFtIHtTdHJpbmd9IGFjY291bnRJZCBpZCBvZiB0aGUgTWV0YUFwaSBhY2NvdW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBpZCBpZCBvZiB0aGUgdHJhY2tlclxuICAgKiBAcmV0dXJuIHtQcm9taXNlfSBwcm9taXNlIHJlc29sdmluZyB3aGVuIHByb2ZpdC9kcmF3ZG93biB0cmFja2VyIHJlbW92ZWRcbiAgICovXG4gIGRlbGV0ZVRyYWNrZXIoYWNjb3VudElkLCBpZCkge1xuICAgIHJldHVybiB0aGlzLl9kb21haW5DbGllbnQucmVxdWVzdEFwaSh7XG4gICAgICB1cmw6IGAvdXNlcnMvY3VycmVudC9hY2NvdW50cy8ke2FjY291bnRJZH0vdHJhY2tlcnMvJHtpZH1gLFxuICAgICAgbWV0aG9kOiAnREVMRVRFJ1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdHJhY2tlciBldmVudHMgYnkgYnJva2VyIHRpbWUgcmFuZ2UuIFNlZVxuICAgKiBodHRwczovL21ldGFhcGkuY2xvdWQvZG9jcy9yaXNrLW1hbmFnZW1lbnQvcmVzdEFwaS9hcGkvZ2V0VHJhY2tlckV2ZW50cy9cbiAgICogQHBhcmFtIHtTdHJpbmd9IFtzdGFydEJyb2tlclRpbWVdIHZhbHVlIG9mIHRoZSBldmVudCB0aW1lIGluIGJyb2tlciB0aW1lem9uZSB0byBzdGFydCBsb2FkaW5nIGRhdGEgZnJvbSwgaW5jbHVzaXZlLFxuICAgKiBpbiAnWVlZWS1NTS1ERCBISDptbTpzcy5TU1MgZm9ybWF0XG4gICAqIEBwYXJhbSB7U3RyaW5nfSBbZW5kQnJva2VyVGltZV0gdmFsdWUgb2YgdGhlIGV2ZW50IHRpbWUgaW4gYnJva2VyIHRpbWV6b25lIHRvIGVuZCBsb2FkaW5nIGRhdGEgYXQsIGluY2x1c2l2ZSxcbiAgICogaW4gJ1lZWVktTU0tREQgSEg6bW06c3MuU1NTIGZvcm1hdFxuICAgKiBAcGFyYW0ge1N0cmluZ30gW2FjY291bnRJZF0gaWQgb2YgdGhlIE1ldGFBcGkgYWNjb3VudFxuICAgKiBAcGFyYW0ge1N0cmluZ30gW3RyYWNrZXJJZF0gaWQgb2YgdGhlIHRyYWNrZXJcbiAgICogQHBhcmFtIHtOdW1iZXJ9IFtsaW1pdF0gcGFnaW5hdGlvbiBsaW1pdCwgZGVmYXVsdCBpcyAxMDAwXG4gICAqIEByZXR1cm4ge1Byb21pc2U8VHJhY2tlckV2ZW50W10+fSBwcm9taXNlIHJlc29sdmluZyB3aXRoIHRyYWNrZXIgZXZlbnRzXG4gICAqL1xuICBnZXRUcmFja2VyRXZlbnRzKHN0YXJ0QnJva2VyVGltZSwgZW5kQnJva2VyVGltZSwgYWNjb3VudElkLCB0cmFja2VySWQsIGxpbWl0KSB7XG4gICAgcmV0dXJuIHRoaXMuX2RvbWFpbkNsaWVudC5yZXF1ZXN0QXBpKHtcbiAgICAgIHVybDogJy91c2Vycy9jdXJyZW50L3RyYWNrZXItZXZlbnRzL2J5LWJyb2tlci10aW1lJyxcbiAgICAgIHBhcmFtczoge3N0YXJ0QnJva2VyVGltZSwgZW5kQnJva2VyVGltZSwgYWNjb3VudElkLCB0cmFja2VySWQsIGxpbWl0fSxcbiAgICAgIG1ldGhvZDogJ0dFVCdcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGEgdHJhY2tlciBldmVudCBsaXN0ZW5lciBhbmQgY3JlYXRlcyBhIGpvYiB0byBtYWtlIHJlcXVlc3RzXG4gICAqIEBwYXJhbSB7VHJhY2tlckV2ZW50TGlzdGVuZXJ9IGxpc3RlbmVyIHRyYWNrZXIgZXZlbnQgbGlzdGVuZXJcbiAgICogQHBhcmFtIHtTdHJpbmd9IFthY2NvdW50SWRdIGFjY291bnQgaWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IFt0cmFja2VySWRdIHRyYWNrZXIgaWRcbiAgICogQHBhcmFtIHtOdW1iZXJ9IFtzZXF1ZW5jZU51bWJlcl0gc2VxdWVuY2UgbnVtYmVyXG4gICAqIEByZXR1cm4ge1N0cmluZ30gbGlzdGVuZXIgaWRcbiAgICovXG4gIGFkZFRyYWNrZXJFdmVudExpc3RlbmVyKGxpc3RlbmVyLCBhY2NvdW50SWQsIHRyYWNrZXJJZCwgc2VxdWVuY2VOdW1iZXIpIHtcbiAgICByZXR1cm4gdGhpcy5fdHJhY2tlckV2ZW50TGlzdGVuZXJNYW5hZ2VyLmFkZFRyYWNrZXJFdmVudExpc3RlbmVyKGxpc3RlbmVyLCBhY2NvdW50SWQsIHRyYWNrZXJJZCwgc2VxdWVuY2VOdW1iZXIpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgdHJhY2tlciBldmVudCBsaXN0ZW5lciBhbmQgY2FuY2VscyB0aGUgZXZlbnQgc3RyZWFtXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBsaXN0ZW5lcklkIHRyYWNrZXIgZXZlbnQgbGlzdGVuZXIgaWRcbiAgICovXG4gIHJlbW92ZVRyYWNrZXJFdmVudExpc3RlbmVyKGxpc3RlbmVySWQpIHtcbiAgICB0aGlzLl90cmFja2VyRXZlbnRMaXN0ZW5lck1hbmFnZXIucmVtb3ZlVHJhY2tlckV2ZW50TGlzdGVuZXIobGlzdGVuZXJJZCk7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBhY2NvdW50IHByb2ZpdCBhbmQgZHJhd2Rvd24gdHJhY2tpbmcgc3RhdGlzdGljcyBieSB0cmFja2VyIGlkLiBTZWVcbiAgICogaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3Mvcmlzay1tYW5hZ2VtZW50L3Jlc3RBcGkvYXBpL2dldFRyYWNraW5nU3RhdHMvXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBhY2NvdW50SWQgaWQgb2YgTWV0YUFQSSBhY2NvdW50XG4gICAqIEBwYXJhbSB7U3RyaW5nfSB0cmFja2VySWQgaWQgb2YgdGhlIHRyYWNrZXJcbiAgICogQHBhcmFtIHtTdHJpbmd9IFtzdGFydFRpbWVdIHRpbWUgdG8gc3RhcnQgbG9hZGluZyBzdGF0cyBmcm9tLCBkZWZhdWx0IGlzIGN1cnJlbnQgdGltZS4gTm90ZSB0aGF0IHN0YXRzIGlzIGxvYWRlZCBpblxuICAgKiBiYWNrd2FyZHMgZGlyZWN0aW9uXG4gICAqIEBwYXJhbSB7TnVtYmVyfSBbbGltaXRdIG51bWJlciBvZiByZWNvcmRzIHRvIGxvYWQsIGRlZmF1bHQgaXMgMVxuICAgKiBAcGFyYW0ge0Jvb2xlYW59IFtyZWFsVGltZV0gaWYgdHJ1ZSwgcmVhbC10aW1lIGRhdGEgd2lsbCBiZSByZXF1ZXN0ZWRcbiAgICogQHJldHVybiB7UHJvbWlzZTxQZXJpb2RTdGF0aXN0aWNzW10+fSBwcm9taXNlIHJlc29sdmluZyB3aXRoIHByb2ZpdCBhbmQgZHJhd2Rvd24gc3RhdGlzdGljc1xuICAgKi9cbiAgZ2V0VHJhY2tpbmdTdGF0aXN0aWNzKGFjY291bnRJZCwgdHJhY2tlcklkLCBzdGFydFRpbWUsIGxpbWl0LCByZWFsVGltZSA9IGZhbHNlKSB7XG4gICAgcmV0dXJuIHRoaXMuX2RvbWFpbkNsaWVudC5yZXF1ZXN0QXBpKHtcbiAgICAgIHVybDogYC91c2Vycy9jdXJyZW50L2FjY291bnRzLyR7YWNjb3VudElkfS90cmFja2Vycy8ke3RyYWNrZXJJZH0vc3RhdGlzdGljc2AsXG4gICAgICBoZWFkZXJzOiB7J2F1dGgtdG9rZW4nOiB0aGlzLl9kb21haW5DbGllbnQudG9rZW4sICdhcGktdmVyc2lvbic6ICcxJ30sXG4gICAgICBwYXJhbXM6IHtzdGFydFRpbWUsIGxpbWl0LCByZWFsVGltZX0sXG4gICAgICBtZXRob2Q6ICdHRVQnXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQWRkcyBhIHBlcmlvZCBzdGF0aXN0aWNzIGV2ZW50IGxpc3RlbmVyXG4gICAqIEBwYXJhbSB7UGVyaW9kU3RhdGlzdGljc0xpc3RlbmVyfSBsaXN0ZW5lciBwZXJpb2Qgc3RhdGlzdGljcyBldmVudCBsaXN0ZW5lclxuICAgKiBAcGFyYW0ge1N0cmluZ30gYWNjb3VudElkIGFjY291bnQgaWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IHRyYWNrZXJJZCB0cmFja2VyIGlkXG4gICAqIEByZXR1cm5zIHtQcm9taXNlPFN0cmluZz59IGxpc3RlbmVyIGlkXG4gICAqL1xuICBhZGRQZXJpb2RTdGF0aXN0aWNzTGlzdGVuZXIobGlzdGVuZXIsIGFjY291bnRJZCwgdHJhY2tlcklkKSB7XG4gICAgcmV0dXJuIHRoaXMuX3BlcmlvZFN0YXRpc3RpY3NTdHJlYW1NYW5hZ2VyLmFkZFBlcmlvZFN0YXRpc3RpY3NMaXN0ZW5lcihsaXN0ZW5lciwgYWNjb3VudElkLCB0cmFja2VySWQpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlbW92ZXMgcGVyaW9kIHN0YXRpc3RpY3MgZXZlbnQgbGlzdGVuZXIgYnkgaWRcbiAgICogQHBhcmFtIHtTdHJpbmd9IGxpc3RlbmVySWQgbGlzdGVuZXIgaWQgXG4gICAqL1xuICByZW1vdmVQZXJpb2RTdGF0aXN0aWNzTGlzdGVuZXIobGlzdGVuZXJJZCkge1xuICAgIHRoaXMuX3BlcmlvZFN0YXRpc3RpY3NTdHJlYW1NYW5hZ2VyLnJlbW92ZVBlcmlvZFN0YXRpc3RpY3NMaXN0ZW5lcihsaXN0ZW5lcklkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGVxdWl0eSBjaGFydCBieSBhY2NvdW50IGlkLiBTZWVcbiAgICogaHR0cHM6Ly9tZXRhYXBpLmNsb3VkL2RvY3Mvcmlzay1tYW5hZ2VtZW50L3Jlc3RBcGkvYXBpL2dldEVxdWl0eUNoYXJ0L1xuICAgKiBAcGFyYW0ge1N0cmluZ30gYWNjb3VudElkIG1ldGFBcGkgYWNjb3VudCBpZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gW3N0YXJ0VGltZV0gc3RhcnRpbmcgYnJva2VyIHRpbWUgaW4gWVlZWS1NTS1ERCBISDptbTpzcyBmb3JtYXRcbiAgICogQHBhcmFtIHtTdHJpbmd9IFtlbmRUaW1lXSBlbmRpbmcgYnJva2VyIHRpbWUgaW4gWVlZWS1NTS1ERCBISDptbTpzcyBmb3JtYXRcbiAgICogQHBhcmFtIHtCb29sZWFufSBbcmVhbFRpbWVdIGlmIHRydWUsIHJlYWwtdGltZSBkYXRhIHdpbGwgYmUgcmVxdWVzdGVkXG4gICAqIEBwYXJhbSB7Qm9vbGVhbn0gW2ZpbGxTa2lwc10gaWYgdHJ1ZSwgc2tpcHBlZCByZWNvcmRzIHdpbGwgYmUgYXV0b21hdGljYWxseSBmaWxsZWQgYmFzZWQgb24gZXhpc3Rpbmcgb25lc1xuICAgKiBAcmV0dXJuIHtQcm9taXNlPEVxdWl0eUNoYXJ0SXRlbVtdPn0gcHJvbWlzZSByZXNvbHZpbmcgd2l0aCBlcXVpdHkgY2hhcnRcbiAgICovXG4gIGFzeW5jIGdldEVxdWl0eUNoYXJ0KGFjY291bnRJZCwgc3RhcnRUaW1lLCBlbmRUaW1lLCByZWFsVGltZSA9IGZhbHNlLCBmaWxsU2tpcHMgPSBmYWxzZSkge1xuICAgIGNvbnN0IHJlY29yZHMgPSBhd2FpdCB0aGlzLl9kb21haW5DbGllbnQucmVxdWVzdEFwaSh7XG4gICAgICB1cmw6IGAvdXNlcnMvY3VycmVudC9hY2NvdW50cy8ke2FjY291bnRJZH0vZXF1aXR5LWNoYXJ0YCxcbiAgICAgIGhlYWRlcnM6IHsnYXV0aC10b2tlbic6IHRoaXMuX2RvbWFpbkNsaWVudC50b2tlbiwgJ2FwaS12ZXJzaW9uJzogJzEnfSxcbiAgICAgIHBhcmFtczoge3N0YXJ0VGltZSwgZW5kVGltZSwgcmVhbFRpbWV9LFxuICAgICAgbWV0aG9kOiAnR0VUJ1xuICAgIH0pO1xuICAgIGlmKGZpbGxTa2lwcyl7XG4gICAgICBsZXQgaSA9IDA7XG4gICAgICB3aGlsZShpIDwgcmVjb3Jkcy5sZW5ndGggLSAxKSB7XG4gICAgICAgIGNvbnN0IHRpbWVEaWZmID0gbmV3IERhdGUocmVjb3Jkc1tpICsgMV0uc3RhcnRCcm9rZXJUaW1lKS5nZXRUaW1lKCkgLSBcbiAgICAgICAgbmV3IERhdGUocmVjb3Jkc1tpXS5zdGFydEJyb2tlclRpbWUpLmdldFRpbWUoKTtcbiAgICAgICAgXG4gICAgICAgIGlmKHRpbWVEaWZmID4gNjAgKiA2MCAqIDEwMDAgJiYgcmVjb3Jkc1tpXS5sYXN0QmFsYW5jZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY29uc3QgcmVjb3JkQ29weSA9IEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkocmVjb3Jkc1tpXSkpO1xuICAgICAgICAgIHJlY29yZENvcHkubWluRXF1aXR5ID0gcmVjb3JkQ29weS5sYXN0RXF1aXR5O1xuICAgICAgICAgIHJlY29yZENvcHkubWF4RXF1aXR5ID0gcmVjb3JkQ29weS5sYXN0RXF1aXR5O1xuICAgICAgICAgIHJlY29yZENvcHkuYXZlcmFnZUVxdWl0eSA9IHJlY29yZENvcHkubGFzdEVxdWl0eTtcbiAgICAgICAgICByZWNvcmRDb3B5Lm1pbkJhbGFuY2UgPSByZWNvcmRDb3B5Lmxhc3RCYWxhbmNlO1xuICAgICAgICAgIHJlY29yZENvcHkubWF4QmFsYW5jZSA9IHJlY29yZENvcHkubGFzdEJhbGFuY2U7XG4gICAgICAgICAgcmVjb3JkQ29weS5hdmVyYWdlQmFsYW5jZSA9IHJlY29yZENvcHkubGFzdEJhbGFuY2U7XG4gICAgICAgICAgY29uc3Qgc3RhcnRCcm9rZXJUaW1lID0gbmV3IERhdGUocmVjb3JkQ29weS5zdGFydEJyb2tlclRpbWUpO1xuICAgICAgICAgIHN0YXJ0QnJva2VyVGltZS5zZXRVVENIb3VycyhzdGFydEJyb2tlclRpbWUuZ2V0VVRDSG91cnMoKSArIDEpO1xuICAgICAgICAgIHN0YXJ0QnJva2VyVGltZS5zZXRVVENNaW51dGVzKDApO1xuICAgICAgICAgIHN0YXJ0QnJva2VyVGltZS5zZXRVVENTZWNvbmRzKDApO1xuICAgICAgICAgIHN0YXJ0QnJva2VyVGltZS5zZXRVVENNaWxsaXNlY29uZHMoMCk7XG4gICAgICAgICAgcmVjb3JkQ29weS5zdGFydEJyb2tlclRpbWUgPSBtb21lbnQoc3RhcnRCcm9rZXJUaW1lKS5mb3JtYXQoJ1lZWVktTU0tREQgSEg6bW06c3MuU1NTJyk7XG4gICAgICAgICAgc3RhcnRCcm9rZXJUaW1lLnNldFVUQ0hvdXJzKHN0YXJ0QnJva2VyVGltZS5nZXRVVENIb3VycygpICsgMSk7XG4gICAgICAgICAgc3RhcnRCcm9rZXJUaW1lLnNldFVUQ01pbGxpc2Vjb25kcygtMSk7XG4gICAgICAgICAgcmVjb3JkQ29weS5lbmRCcm9rZXJUaW1lID0gbW9tZW50KHN0YXJ0QnJva2VyVGltZSkuZm9ybWF0KCdZWVlZLU1NLUREIEhIOm1tOnNzLlNTUycpO1xuICAgICAgICAgIHJlY29yZENvcHkuYnJva2VyVGltZSA9IHJlY29yZENvcHkuZW5kQnJva2VyVGltZTtcbiAgICAgICAgICByZWNvcmRzLnNwbGljZShpICsgMSwgMCwgcmVjb3JkQ29weSk7XG4gICAgICAgIH1cbiAgICAgICAgaSsrO1xuICAgICAgfSAgXG4gICAgfVxuICAgIHJldHVybiByZWNvcmRzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZHMgYW4gZXF1aXR5IGNoYXJ0IGV2ZW50IGxpc3RlbmVyXG4gICAqIEBwYXJhbSB7RXF1aXR5Q2hhcnRMaXN0ZW5lcn0gbGlzdGVuZXIgZXF1aXR5IGNoYXJ0IGV2ZW50IGxpc3RlbmVyXG4gICAqIEBwYXJhbSB7U3RyaW5nfSBhY2NvdW50SWQgYWNjb3VudCBpZFxuICAgKiBAcGFyYW0ge0RhdGV9IFtzdGFydFRpbWVdIGRhdGUgdG8gc3RhcnQgdHJhY2tpbmcgZnJvbVxuICAgKiBAcmV0dXJucyB7UHJvbWlzZTxzdHJpbmc+fSBsaXN0ZW5lciBpZFxuICAgKi9cbiAgYWRkRXF1aXR5Q2hhcnRMaXN0ZW5lcihsaXN0ZW5lciwgYWNjb3VudElkLCBzdGFydFRpbWUpIHtcbiAgICByZXR1cm4gdGhpcy5fZXF1aXR5Q2hhcnRTdHJlYW1NYW5hZ2VyLmFkZEVxdWl0eUNoYXJ0TGlzdGVuZXIobGlzdGVuZXIsIGFjY291bnRJZCwgc3RhcnRUaW1lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGVxdWl0eSBjaGFydCBldmVudCBsaXN0ZW5lciBieSBpZFxuICAgKiBAcGFyYW0ge1N0cmluZ30gbGlzdGVuZXJJZCBlcXVpdHkgY2hhcnQgbGlzdGVuZXIgaWQgXG4gICAqL1xuICByZW1vdmVFcXVpdHlDaGFydExpc3RlbmVyKGxpc3RlbmVySWQpIHtcbiAgICB0aGlzLl9lcXVpdHlDaGFydFN0cmVhbU1hbmFnZXIucmVtb3ZlRXF1aXR5Q2hhcnRMaXN0ZW5lcihsaXN0ZW5lcklkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGRzIGFuIGVxdWl0eSBiYWxhbmNlIGV2ZW50IGxpc3RlbmVyXG4gICAqIEBwYXJhbSB7RXF1aXR5QmFsYW5jZUxpc3RlbmVyfSBsaXN0ZW5lciBlcXVpdHkgYmFsYW5jZSBldmVudCBsaXN0ZW5lclxuICAgKiBAcGFyYW0ge3N0cmluZ30gYWNjb3VudElkIGFjY291bnQgaWRcbiAgICogQHJldHVybnMge1Byb21pc2U8c3RyaW5nPn0gbGlzdGVuZXIgaWRcbiAgICovXG4gIGFkZEVxdWl0eUJhbGFuY2VMaXN0ZW5lcihsaXN0ZW5lciwgYWNjb3VudElkKSB7XG4gICAgcmV0dXJuIHRoaXMuX2VxdWl0eUJhbGFuY2VTdHJlYW1NYW5hZ2VyLmFkZEVxdWl0eUJhbGFuY2VMaXN0ZW5lcihsaXN0ZW5lciwgYWNjb3VudElkKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZW1vdmVzIGVxdWl0eSBiYWxhbmNlIGV2ZW50IGxpc3RlbmVyIGJ5IGlkXG4gICAqIEBwYXJhbSB7c3RyaW5nfSBsaXN0ZW5lcklkIGVxdWl0eSBiYWxhbmNlIGxpc3RlbmVyIGlkIFxuICAgKi9cbiAgcmVtb3ZlRXF1aXR5QmFsYW5jZUxpc3RlbmVyKGxpc3RlbmVySWQpIHtcbiAgICB0aGlzLl9lcXVpdHlCYWxhbmNlU3RyZWFtTWFuYWdlci5yZW1vdmVFcXVpdHlCYWxhbmNlTGlzdGVuZXIobGlzdGVuZXJJZCk7XG4gIH1cblxufVxuIl0sIm5hbWVzIjpbIkVxdWl0eVRyYWNraW5nQ2xpZW50IiwiY3JlYXRlVHJhY2tlciIsImFjY291bnRJZCIsInRyYWNrZXIiLCJfZG9tYWluQ2xpZW50IiwicmVxdWVzdEFwaSIsInVybCIsImhlYWRlcnMiLCJ0b2tlbiIsIm1ldGhvZCIsImRhdGEiLCJnZXRUcmFja2VycyIsImdldFRyYWNrZXIiLCJpZCIsImdldFRyYWNrZXJCeU5hbWUiLCJuYW1lIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwidXBkYXRlVHJhY2tlciIsInVwZGF0ZSIsImRlbGV0ZVRyYWNrZXIiLCJnZXRUcmFja2VyRXZlbnRzIiwic3RhcnRCcm9rZXJUaW1lIiwiZW5kQnJva2VyVGltZSIsInRyYWNrZXJJZCIsImxpbWl0IiwicGFyYW1zIiwiYWRkVHJhY2tlckV2ZW50TGlzdGVuZXIiLCJsaXN0ZW5lciIsInNlcXVlbmNlTnVtYmVyIiwiX3RyYWNrZXJFdmVudExpc3RlbmVyTWFuYWdlciIsInJlbW92ZVRyYWNrZXJFdmVudExpc3RlbmVyIiwibGlzdGVuZXJJZCIsImdldFRyYWNraW5nU3RhdGlzdGljcyIsInN0YXJ0VGltZSIsInJlYWxUaW1lIiwiYWRkUGVyaW9kU3RhdGlzdGljc0xpc3RlbmVyIiwiX3BlcmlvZFN0YXRpc3RpY3NTdHJlYW1NYW5hZ2VyIiwicmVtb3ZlUGVyaW9kU3RhdGlzdGljc0xpc3RlbmVyIiwiZ2V0RXF1aXR5Q2hhcnQiLCJlbmRUaW1lIiwiZmlsbFNraXBzIiwicmVjb3JkcyIsImkiLCJsZW5ndGgiLCJ0aW1lRGlmZiIsIkRhdGUiLCJnZXRUaW1lIiwibGFzdEJhbGFuY2UiLCJ1bmRlZmluZWQiLCJyZWNvcmRDb3B5IiwiSlNPTiIsInBhcnNlIiwic3RyaW5naWZ5IiwibWluRXF1aXR5IiwibGFzdEVxdWl0eSIsIm1heEVxdWl0eSIsImF2ZXJhZ2VFcXVpdHkiLCJtaW5CYWxhbmNlIiwibWF4QmFsYW5jZSIsImF2ZXJhZ2VCYWxhbmNlIiwic2V0VVRDSG91cnMiLCJnZXRVVENIb3VycyIsInNldFVUQ01pbnV0ZXMiLCJzZXRVVENTZWNvbmRzIiwic2V0VVRDTWlsbGlzZWNvbmRzIiwibW9tZW50IiwiZm9ybWF0IiwiYnJva2VyVGltZSIsInNwbGljZSIsImFkZEVxdWl0eUNoYXJ0TGlzdGVuZXIiLCJfZXF1aXR5Q2hhcnRTdHJlYW1NYW5hZ2VyIiwicmVtb3ZlRXF1aXR5Q2hhcnRMaXN0ZW5lciIsImFkZEVxdWl0eUJhbGFuY2VMaXN0ZW5lciIsIl9lcXVpdHlCYWxhbmNlU3RyZWFtTWFuYWdlciIsInJlbW92ZUVxdWl0eUJhbGFuY2VMaXN0ZW5lciIsImNvbnN0cnVjdG9yIiwiZG9tYWluQ2xpZW50IiwibWV0YUFwaSIsIlRyYWNrZXJFdmVudExpc3RlbmVyTWFuYWdlciIsIkVxdWl0eUJhbGFuY2VTdHJlYW1NYW5hZ2VyIiwiUGVyaW9kU3RhdGlzdGljc1N0cmVhbU1hbmFnZXIiLCJFcXVpdHlDaGFydFN0cmVhbU1hbmFnZXIiXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7O2VBV3FCQTs7O29GQVRtQjtzRkFDRTtpRkFDTDttRkFDRTsrREFDcEI7Ozs7OztBQUtKLElBQUEsQUFBTUEsdUJBQU4sTUFBTUE7SUFlbkI7Ozs7OztHQU1DLEdBQ0RDLGNBQWNDLFNBQVMsRUFBRUMsT0FBTyxFQUFFO1FBQ2hDLE9BQU8sSUFBSSxDQUFDQyxhQUFhLENBQUNDLFVBQVUsQ0FBQztZQUNuQ0MsS0FBSyxDQUFD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