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) • 32.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "default", {
enumerable: true,
get: function() {
return Reservoir;
}
});
let Reservoir = class Reservoir {
checkStatisticsOnRestore(statistics) {
if (statistics.count === 0) {
statistics = {
count: 0,
sum: 0,
max: undefined,
min: undefined,
average: undefined,
sumOfSquares: 0,
msdev: undefined,
stddev: undefined
};
} else if (statistics.count < 2) {
statistics.msdev = undefined;
statistics.stddev = undefined;
}
return statistics;
}
/**
* Add element to Reservoir
* @param {Number} data to add
*/ pushMeasurement(data) {
if (isFinite(data)) {
this._updateQueue();
this._updateIntermediaryRecord(data);
this._updateStatisticsOnAdd(data);
}
}
/**
* return Reservoir statistics
* @return {Object} Reservoir statistics
*/ getStatistics() {
this._updateQueue();
return this.statistics;
}
toPlainObject() {
this._updateQueue(true);
return {
array: this.array,
size: this.size,
_interval: this._interval,
_queueEndTime: this._queueEndTime,
_fisrtQueueIndex: this._fisrtQueueIndex,
_intermediaryRecord: this._intermediaryRecord,
statistics: this.statistics
};
}
_updateQueue() {
let intervalsCount = this._takeTimeIntervalsCount();
let emptyElementsCount = this._takeEmptyElementsAddCount();
if (emptyElementsCount > 0) {
this._addRecord(emptyElementsCount);
this._queueEndTime += intervalsCount * this._interval;
}
}
_takeEmptyElementsAddCount() {
let emptyElementsCount = this._takeTimeIntervalsCount();
if (emptyElementsCount > this.size) {
emptyElementsCount = this.size;
}
return emptyElementsCount;
}
_takeTimeIntervalsCount() {
let timeNow = Date.now();
let timeDiff = timeNow - this._queueEndTime;
let timeIntervalsCount = Math.floor(timeDiff / this._interval);
return timeIntervalsCount;
}
_updateRunningStatisticsOnRemove(removeCount) {
let removeElementIndex = this._fisrtQueueIndex + 1;
for(let i = 0; i < removeCount; i++){
if (removeElementIndex >= this.size) {
removeElementIndex = 0;
}
this._updateStatisticsOnRemove(this.array[removeElementIndex], removeElementIndex);
this.array[removeElementIndex] = {
count: 0,
sum: 0,
max: undefined,
min: undefined,
average: 0,
sumOfSquares: 0
};
removeElementIndex++;
}
removeElementIndex--;
if (removeElementIndex < 0) {
removeElementIndex = this.size - 1;
}
return removeElementIndex;
}
_updateStatisticsOnRemove(removeElement, removeElementIndex) {
if (removeElement !== undefined && removeElement !== null) {
this.statistics.count -= removeElement.count;
this.statistics.sumOfSquares -= removeElement.sumOfSquares;
this.statistics.sum -= removeElement.sum;
this._updateStatisticsMinAndMaxOnRemove(removeElement, removeElementIndex);
if (this.statistics.count > 0) {
this.statistics.average = this.statistics.sum / this.statistics.count;
if (this.statistics.count > 1) {
let difOfSums = this._calculateDifferenceOfSums(this.statistics.sumOfSquares, this.statistics.sum, this.statistics.count);
this.statistics.msdev = parseFloat(Math.sqrt(difOfSums / this.statistics.count));
this.statistics.stddev = parseFloat(Math.sqrt(difOfSums / (this.statistics.count - 1)));
} else {
this.statistics.stddev = undefined;
this.statistics.msdev = undefined;
}
} else {
this.statistics.average = undefined;
this.statistics.stddev = undefined;
this.statistics.msdev = undefined;
}
}
}
_updateStatisticsMinAndMaxOnRemove(removeElement, removeElementIndex) {
if (removeElement.max !== undefined && removeElement.max === this.statistics.max) {
this.statistics.max = this._findMax(removeElementIndex);
}
if (removeElement.min !== undefined && removeElement.min === this.statistics.min) {
this.statistics.min = this._findMin(removeElementIndex);
}
}
_updateStatisticsOnAdd(el) {
if (el !== undefined && el !== null) {
this.statistics.count += 1;
this.statistics.sum += el;
this._updateStatisticsMinAndMaxOnAdd(el);
this.statistics.sumOfSquares += Math.pow(el, 2);
if (this.statistics.count > 0) {
this.statistics.average = this.statistics.sum / this.statistics.count;
let difOfSums = this._calculateDifferenceOfSums(this.statistics.sumOfSquares, this.statistics.sum, this.statistics.count);
if (this.statistics.count > 1) {
this.statistics.msdev = parseFloat(Math.sqrt(difOfSums / this.statistics.count));
this.statistics.stddev = parseFloat(Math.sqrt(difOfSums / (this.statistics.count - 1)));
} else {
this.statistics.msdev = undefined;
this.statistics.stddev = undefined;
}
}
}
}
_updateStatisticsMinAndMaxOnAdd(el) {
if (this.statistics.max < el || this.statistics.max === undefined || this.statistics.max === null) {
this.statistics.max = el;
}
if (this.statistics.min > el || this.statistics.min === undefined || this.statistics.min === null) {
this.statistics.min = el;
}
}
_addRecord(emptyElementsCount) {
if (this._intermediaryRecord !== undefined) {
this.array[this._fisrtQueueIndex] = this._intermediaryRecord;
this._intermediaryRecord = undefined;
}
let curIndexInArray = this._updateRunningStatisticsOnRemove(emptyElementsCount);
this._fisrtQueueIndex = curIndexInArray;
}
_calculateDifferenceOfSums(sum1, sum2, count) {
let dif = sum1 - Math.pow(sum2, 2) / count;
return dif;
}
_updateIntermediaryRecord(el) {
if (this._intermediaryRecord === undefined) {
this._intermediaryRecord = {
count: 1,
sum: el,
max: el,
min: el,
average: el,
sumOfSquares: Math.pow(el, 2)
};
} else {
if (this._intermediaryRecord.max < el) {
this._intermediaryRecord.max = el;
}
if (this._intermediaryRecord.min > el) {
this._intermediaryRecord.min = el;
}
this._intermediaryRecord.count += 1;
this._intermediaryRecord.sum += el;
this._intermediaryRecord.sumOfSquares += Math.pow(el, 2);
}
}
_findMin(index) {
let min = Infinity;
this.array.forEach((el, i)=>{
if (el !== null && el !== undefined && el.min !== undefined && el.min < min && i !== index) {
min = el.min;
}
});
if (min === Infinity) {
return this._intermediaryRecord !== undefined ? this._intermediaryRecord.min : undefined;
}
return min;
}
_findMax(index) {
let max = -Infinity;
this.array.forEach((el, i)=>{
if (el !== null && el !== undefined && el.max !== undefined && el.max > max && i !== index) {
max = el.max;
}
});
if (max === -Infinity) {
return this._intermediaryRecord !== undefined ? this._intermediaryRecord.max : undefined;
}
return max;
}
/**
* Constructs Reservoir
* @param {number} size Reservoir size
* @param {number} observationIntervalInMS Reservoir observation Interval In ms
*/ constructor(size, observationIntervalInMS, object){
if (!object) {
this.array = [];
this.size = size;
this._interval = observationIntervalInMS / size;
this._queueEndTime = Date.now();
this._fisrtQueueIndex = 0;
this._intermediaryRecord = undefined;
this.statistics = {
count: 0,
sum: 0,
max: undefined,
min: undefined,
average: 0,
sumOfSquares: 0,
msdev: 0,
stddev: 0
};
} else {
this.array = object.array;
this.size = object.size;
this._interval = object._interval;
this._queueEndTime = object._queueEndTime;
this._fisrtQueueIndex = object._fisrtQueueIndex;
this._intermediaryRecord = object._intermediaryRecord;
this.statistics = this.checkStatisticsOnRestore(object.statistics);
}
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbi8qKlxuICogRklGTy1saWtlIHJlc2Vydm9pciBvZiBhIGZpeGVkIHNpemUgY2FwYWJsZVxuICogY2FsY3VsYXRpbmcgcnVubmluZyBzdW1zLCBtaW4vbWF4LCBhdmVyYWdlLCBtc2RldiBhbmQgc3RkZGV2XG4gKiBtc2RldiBhbmQgc3RkZGV2IGNhbGN1bGF0aW9uIGJ5IE5haXZlIGFsZ29yaXRobVxuICogKE1lYW4gc3F1YXJlIGRldmlhdGlvbikgbXNkZXYgPSBzcXJ0KCjiiJF7aSA9IGZyb20gMSB0byBufShYaSleMiAtKOKIkXtpID0gZnJvbSAxIHRvIG59WGkpXjIgLyBOKSAvIE4pXG4gKiAoU3RhbmRhcmQgZGV2aWF0aW9uKSBzdGRkZXYgPSBzcXJ0KCjiiJF7aSA9IGZyb20gMSB0byBufShYaSleMiAtKOKIkXtpID0gZnJvbSAxIHRvIG59WGkpXjIgLyBOKSAvIE4gLSAxKVxuICogbGluazogaHR0cHM6Ly9nb28uZ2wvTUFFR1AyXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIFJlc2Vydm9pciB7XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdHMgUmVzZXJ2b2lyXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBzaXplIFJlc2Vydm9pciBzaXplXG4gICAqIEBwYXJhbSB7bnVtYmVyfSBvYnNlcnZhdGlvbkludGVydmFsSW5NUyBSZXNlcnZvaXIgb2JzZXJ2YXRpb24gSW50ZXJ2YWwgSW4gbXNcbiAgICovXG4gIGNvbnN0cnVjdG9yKHNpemUsIG9ic2VydmF0aW9uSW50ZXJ2YWxJbk1TLCBvYmplY3QpIHtcbiAgICBpZiAoIW9iamVjdCkge1xuICAgICAgdGhpcy5hcnJheSA9IFtdO1xuICAgICAgdGhpcy5zaXplID0gc2l6ZTtcbiAgICAgIHRoaXMuX2ludGVydmFsID0gKG9ic2VydmF0aW9uSW50ZXJ2YWxJbk1TIC8gc2l6ZSk7XG4gICAgICB0aGlzLl9xdWV1ZUVuZFRpbWUgPSBEYXRlLm5vdygpO1xuICAgICAgdGhpcy5fZmlzcnRRdWV1ZUluZGV4ID0gMDtcbiAgICAgIHRoaXMuX2ludGVybWVkaWFyeVJlY29yZCA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMuc3RhdGlzdGljcyA9IHtcbiAgICAgICAgY291bnQ6IDAsXG4gICAgICAgIHN1bTogMCxcbiAgICAgICAgbWF4OiB1bmRlZmluZWQsXG4gICAgICAgIG1pbjogdW5kZWZpbmVkLFxuICAgICAgICBhdmVyYWdlOiAwLFxuICAgICAgICBzdW1PZlNxdWFyZXM6IDAsXG4gICAgICAgIG1zZGV2OiAwLFxuICAgICAgICBzdGRkZXY6IDBcbiAgICAgIH07XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuYXJyYXkgPSBvYmplY3QuYXJyYXk7XG4gICAgICB0aGlzLnNpemUgPSBvYmplY3Quc2l6ZTtcbiAgICAgIHRoaXMuX2ludGVydmFsID0gb2JqZWN0Ll9pbnRlcnZhbDtcbiAgICAgIHRoaXMuX3F1ZXVlRW5kVGltZSA9IG9iamVjdC5fcXVldWVFbmRUaW1lO1xuICAgICAgdGhpcy5fZmlzcnRRdWV1ZUluZGV4ID0gb2JqZWN0Ll9maXNydFF1ZXVlSW5kZXg7XG4gICAgICB0aGlzLl9pbnRlcm1lZGlhcnlSZWNvcmQgPSBvYmplY3QuX2ludGVybWVkaWFyeVJlY29yZDtcbiAgICAgIHRoaXMuc3RhdGlzdGljcyA9IHRoaXMuY2hlY2tTdGF0aXN0aWNzT25SZXN0b3JlKG9iamVjdC5zdGF0aXN0aWNzKTtcbiAgICB9XG4gIH1cblxuICBjaGVja1N0YXRpc3RpY3NPblJlc3RvcmUoc3RhdGlzdGljcykge1xuICAgIGlmIChzdGF0aXN0aWNzLmNvdW50ID09PSAwKSB7XG4gICAgICBzdGF0aXN0aWNzID0ge1xuICAgICAgICBjb3VudDogMCxcbiAgICAgICAgc3VtOiAwLFxuICAgICAgICBtYXg6IHVuZGVmaW5lZCxcbiAgICAgICAgbWluOiB1bmRlZmluZWQsXG4gICAgICAgIGF2ZXJhZ2U6IHVuZGVmaW5lZCxcbiAgICAgICAgc3VtT2ZTcXVhcmVzOiAwLFxuICAgICAgICBtc2RldjogdW5kZWZpbmVkLFxuICAgICAgICBzdGRkZXY6IHVuZGVmaW5lZFxuICAgICAgfTtcbiAgICB9IGVsc2UgaWYgKHN0YXRpc3RpY3MuY291bnQgPCAyKSB7XG4gICAgICBzdGF0aXN0aWNzLm1zZGV2ID0gdW5kZWZpbmVkO1xuICAgICAgc3RhdGlzdGljcy5zdGRkZXYgPSB1bmRlZmluZWQ7XG4gICAgfVxuICAgIHJldHVybiBzdGF0aXN0aWNzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBlbGVtZW50IHRvIFJlc2Vydm9pclxuICAgKiBAcGFyYW0ge051bWJlcn0gZGF0YSB0byBhZGRcbiAgICovXG4gIHB1c2hNZWFzdXJlbWVudChkYXRhKSB7XG4gICAgaWYgKGlzRmluaXRlKGRhdGEpKSB7XG4gICAgICB0aGlzLl91cGRhdGVRdWV1ZSgpO1xuICAgICAgdGhpcy5fdXBkYXRlSW50ZXJtZWRpYXJ5UmVjb3JkKGRhdGEpO1xuICAgICAgdGhpcy5fdXBkYXRlU3RhdGlzdGljc09uQWRkKGRhdGEpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiByZXR1cm4gUmVzZXJ2b2lyIHN0YXRpc3RpY3NcbiAgICogQHJldHVybiB7T2JqZWN0fSBSZXNlcnZvaXIgc3RhdGlzdGljc1xuICAgKi9cbiAgZ2V0U3RhdGlzdGljcygpIHtcbiAgICB0aGlzLl91cGRhdGVRdWV1ZSgpO1xuICAgIHJldHVybiB0aGlzLnN0YXRpc3RpY3M7XG4gIH1cblxuICB0b1BsYWluT2JqZWN0KCkge1xuICAgIHRoaXMuX3VwZGF0ZVF1ZXVlKHRydWUpO1xuICAgIHJldHVybiB7XG4gICAgICBhcnJheTogdGhpcy5hcnJheSxcbiAgICAgIHNpemU6IHRoaXMuc2l6ZSxcbiAgICAgIF9pbnRlcnZhbDogdGhpcy5faW50ZXJ2YWwsXG4gICAgICBfcXVldWVFbmRUaW1lOiB0aGlzLl9xdWV1ZUVuZFRpbWUsXG4gICAgICBfZmlzcnRRdWV1ZUluZGV4OiB0aGlzLl9maXNydFF1ZXVlSW5kZXgsXG4gICAgICBfaW50ZXJtZWRpYXJ5UmVjb3JkOiB0aGlzLl9pbnRlcm1lZGlhcnlSZWNvcmQsXG4gICAgICBzdGF0aXN0aWNzOiB0aGlzLnN0YXRpc3RpY3NcbiAgICB9O1xuICB9XG5cbiAgX3VwZGF0ZVF1ZXVlKCkge1xuICAgIGxldCBpbnRlcnZhbHNDb3VudCA9IHRoaXMuX3Rha2VUaW1lSW50ZXJ2YWxzQ291bnQoKTtcbiAgICBsZXQgZW1wdHlFbGVtZW50c0NvdW50ID0gdGhpcy5fdGFrZUVtcHR5RWxlbWVudHNBZGRDb3VudCgpO1xuICAgIGlmIChlbXB0eUVsZW1lbnRzQ291bnQgPiAwKSB7XG4gICAgICB0aGlzLl9hZGRSZWNvcmQoZW1wdHlFbGVtZW50c0NvdW50KTtcbiAgICAgIHRoaXMuX3F1ZXVlRW5kVGltZSArPSBpbnRlcnZhbHNDb3VudCAqIHRoaXMuX2ludGVydmFsO1xuICAgIH1cbiAgfVxuXG4gIF90YWtlRW1wdHlFbGVtZW50c0FkZENvdW50KCkge1xuICAgIGxldCBlbXB0eUVsZW1lbnRzQ291bnQgPSB0aGlzLl90YWtlVGltZUludGVydmFsc0NvdW50KCk7XG4gICAgaWYgKGVtcHR5RWxlbWVudHNDb3VudCA+IHRoaXMuc2l6ZSkge1xuICAgICAgZW1wdHlFbGVtZW50c0NvdW50ID0gdGhpcy5zaXplO1xuICAgIH1cbiAgICByZXR1cm4gZW1wdHlFbGVtZW50c0NvdW50O1xuICB9XG5cbiAgX3Rha2VUaW1lSW50ZXJ2YWxzQ291bnQoKSB7XG4gICAgbGV0IHRpbWVOb3cgPSBEYXRlLm5vdygpO1xuICAgIGxldCB0aW1lRGlmZiA9IHRpbWVOb3cgLSB0aGlzLl9xdWV1ZUVuZFRpbWU7XG4gICAgbGV0IHRpbWVJbnRlcnZhbHNDb3VudCA9IE1hdGguZmxvb3IodGltZURpZmYgLyB0aGlzLl9pbnRlcnZhbCk7XG4gICAgcmV0dXJuIHRpbWVJbnRlcnZhbHNDb3VudDtcbiAgfVxuXG4gIF91cGRhdGVSdW5uaW5nU3RhdGlzdGljc09uUmVtb3ZlKHJlbW92ZUNvdW50KSB7XG4gICAgbGV0IHJlbW92ZUVsZW1lbnRJbmRleCA9IHRoaXMuX2Zpc3J0UXVldWVJbmRleCArIDE7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCByZW1vdmVDb3VudDsgaSsrKSB7XG4gICAgICBpZiAocmVtb3ZlRWxlbWVudEluZGV4ID49IHRoaXMuc2l6ZSkge1xuICAgICAgICByZW1vdmVFbGVtZW50SW5kZXggPSAwO1xuICAgICAgfVxuXG4gICAgICB0aGlzLl91cGRhdGVTdGF0aXN0aWNzT25SZW1vdmUodGhpcy5hcnJheVtyZW1vdmVFbGVtZW50SW5kZXhdLCByZW1vdmVFbGVtZW50SW5kZXgpO1xuICAgICAgdGhpcy5hcnJheVtyZW1vdmVFbGVtZW50SW5kZXhdID0ge1xuICAgICAgICBjb3VudDogMCxcbiAgICAgICAgc3VtOiAwLFxuICAgICAgICBtYXg6IHVuZGVmaW5lZCxcbiAgICAgICAgbWluOiB1bmRlZmluZWQsXG4gICAgICAgIGF2ZXJhZ2U6IDAsXG4gICAgICAgIHN1bU9mU3F1YXJlczogMFxuICAgICAgfTtcbiAgICAgIHJlbW92ZUVsZW1lbnRJbmRleCsrO1xuICAgIH1cbiAgICByZW1vdmVFbGVtZW50SW5kZXgtLTtcbiAgICBpZiAocmVtb3ZlRWxlbWVudEluZGV4IDwgMCkge1xuICAgICAgcmVtb3ZlRWxlbWVudEluZGV4ID0gdGhpcy5zaXplIC0gMTtcbiAgICB9XG4gICAgcmV0dXJuIHJlbW92ZUVsZW1lbnRJbmRleDtcbiAgfVxuXG4gIF91cGRhdGVTdGF0aXN0aWNzT25SZW1vdmUocmVtb3ZlRWxlbWVudCwgcmVtb3ZlRWxlbWVudEluZGV4KSB7XG4gICAgaWYgKHJlbW92ZUVsZW1lbnQgIT09IHVuZGVmaW5lZCAmJiByZW1vdmVFbGVtZW50ICE9PSBudWxsKSB7XG4gICAgICB0aGlzLnN0YXRpc3RpY3MuY291bnQgLT0gcmVtb3ZlRWxlbWVudC5jb3VudDtcbiAgICAgIHRoaXMuc3RhdGlzdGljcy5zdW1PZlNxdWFyZXMgLT0gcmVtb3ZlRWxlbWVudC5zdW1PZlNxdWFyZXM7XG4gICAgICB0aGlzLnN0YXRpc3RpY3Muc3VtIC09IHJlbW92ZUVsZW1lbnQuc3VtO1xuICAgICAgdGhpcy5fdXBkYXRlU3RhdGlzdGljc01pbkFuZE1heE9uUmVtb3ZlKHJlbW92ZUVsZW1lbnQsIHJlbW92ZUVsZW1lbnRJbmRleCk7XG4gICAgICBpZiAodGhpcy5zdGF0aXN0aWNzLmNvdW50ID4gMCkge1xuICAgICAgICB0aGlzLnN0YXRpc3RpY3MuYXZlcmFnZSA9IHRoaXMuc3RhdGlzdGljcy5zdW0gLyB0aGlzLnN0YXRpc3RpY3MuY291bnQ7XG4gICAgICAgIGlmICh0aGlzLnN0YXRpc3RpY3MuY291bnQgPiAxKSB7XG4gICAgICAgICAgbGV0IGRpZk9mU3VtcyA9IHRoaXMuX2NhbGN1bGF0ZURpZmZlcmVuY2VPZlN1bXModGhpcy5zdGF0aXN0aWNzLnN1bU9mU3F1YXJlcyxcbiAgICAgICAgICAgIHRoaXMuc3RhdGlzdGljcy5zdW0sIHRoaXMuc3RhdGlzdGljcy5jb3VudCk7XG4gICAgICAgICAgdGhpcy5zdGF0aXN0aWNzLm1zZGV2ID0gcGFyc2VGbG9hdChNYXRoLnNxcnQoZGlmT2ZTdW1zIC8gdGhpcy5zdGF0aXN0aWNzLmNvdW50KSk7XG4gICAgICAgICAgdGhpcy5zdGF0aXN0aWNzLnN0ZGRldiA9IHBhcnNlRmxvYXQoTWF0aC5zcXJ0KGRpZk9mU3VtcyAvICh0aGlzLnN0YXRpc3RpY3MuY291bnQgLSAxKSkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuc3RhdGlzdGljcy5zdGRkZXYgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgdGhpcy5zdGF0aXN0aWNzLm1zZGV2ID0gdW5kZWZpbmVkO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnN0YXRpc3RpY3MuYXZlcmFnZSA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5zdGF0aXN0aWNzLnN0ZGRldiA9IHVuZGVmaW5lZDtcbiAgICAgICAgdGhpcy5zdGF0aXN0aWNzLm1zZGV2ID0gdW5kZWZpbmVkO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIF91cGRhdGVTdGF0aXN0aWNzTWluQW5kTWF4T25SZW1vdmUocmVtb3ZlRWxlbWVudCwgcmVtb3ZlRWxlbWVudEluZGV4KSB7XG4gICAgaWYgKHJlbW92ZUVsZW1lbnQubWF4ICE9PSB1bmRlZmluZWQgJiYgcmVtb3ZlRWxlbWVudC5tYXggPT09IHRoaXMuc3RhdGlzdGljcy5tYXgpIHtcbiAgICAgIHRoaXMuc3RhdGlzdGljcy5tYXggPSB0aGlzLl9maW5kTWF4KHJlbW92ZUVsZW1lbnRJbmRleCk7XG4gICAgfVxuXG4gICAgaWYgKHJlbW92ZUVsZW1lbnQubWluICE9PSB1bmRlZmluZWQgJiYgcmVtb3ZlRWxlbWVudC5taW4gPT09IHRoaXMuc3RhdGlzdGljcy5taW4pIHtcbiAgICAgIHRoaXMuc3RhdGlzdGljcy5taW4gPSB0aGlzLl9maW5kTWluKHJlbW92ZUVsZW1lbnRJbmRleCk7XG4gICAgfVxuICB9XG5cbiAgX3VwZGF0ZVN0YXRpc3RpY3NPbkFkZChlbCkge1xuICAgIGlmIChlbCAhPT0gdW5kZWZpbmVkICYmIGVsICE9PSBudWxsKSB7XG4gICAgICB0aGlzLnN0YXRpc3RpY3MuY291bnQgKz0gMTtcbiAgICAgIHRoaXMuc3RhdGlzdGljcy5zdW0gKz0gZWw7XG4gICAgICB0aGlzLl91cGRhdGVTdGF0aXN0aWNzTWluQW5kTWF4T25BZGQoZWwpO1xuICAgICAgdGhpcy5zdGF0aXN0aWNzLnN1bU9mU3F1YXJlcyArPSBNYXRoLnBvdyhlbCwgMik7XG4gICAgICBpZiAodGhpcy5zdGF0aXN0aWNzLmNvdW50ID4gMCkge1xuICAgICAgICB0aGlzLnN0YXRpc3RpY3MuYXZlcmFnZSA9IHRoaXMuc3RhdGlzdGljcy5zdW0gLyB0aGlzLnN0YXRpc3RpY3MuY291bnQ7XG4gICAgICAgIGxldCBkaWZPZlN1bXMgPSB0aGlzLl9jYWxjdWxhdGVEaWZmZXJlbmNlT2ZTdW1zKHRoaXMuc3RhdGlzdGljcy5zdW1PZlNxdWFyZXMsXG4gICAgICAgICAgdGhpcy5zdGF0aXN0aWNzLnN1bSwgdGhpcy5zdGF0aXN0aWNzLmNvdW50KTtcbiAgICAgICAgaWYgKHRoaXMuc3RhdGlzdGljcy5jb3VudCA+IDEpIHtcbiAgICAgICAgICB0aGlzLnN0YXRpc3RpY3MubXNkZXYgPSBwYXJzZUZsb2F0KE1hdGguc3FydChkaWZPZlN1bXMgLyB0aGlzLnN0YXRpc3RpY3MuY291bnQpKTtcbiAgICAgICAgICB0aGlzLnN0YXRpc3RpY3Muc3RkZGV2ID0gcGFyc2VGbG9hdChNYXRoLnNxcnQoZGlmT2ZTdW1zIC8gKHRoaXMuc3RhdGlzdGljcy5jb3VudCAtIDEpKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5zdGF0aXN0aWNzLm1zZGV2ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIHRoaXMuc3RhdGlzdGljcy5zdGRkZXYgPSB1bmRlZmluZWQ7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBfdXBkYXRlU3RhdGlzdGljc01pbkFuZE1heE9uQWRkKGVsKSB7XG4gICAgaWYgKHRoaXMuc3RhdGlzdGljcy5tYXggPCBlbCB8fCB0aGlzLnN0YXRpc3RpY3MubWF4ID09PSB1bmRlZmluZWQgfHwgdGhpcy5zdGF0aXN0aWNzLm1heCA9PT0gbnVsbCkge1xuICAgICAgdGhpcy5zdGF0aXN0aWNzLm1heCA9IGVsO1xuICAgIH1cbiAgICBpZiAodGhpcy5zdGF0aXN0aWNzLm1pbiA+IGVsIHx8IHRoaXMuc3RhdGlzdGljcy5taW4gPT09IHVuZGVmaW5lZCB8fCB0aGlzLnN0YXRpc3RpY3MubWluID09PSBudWxsKSB7XG4gICAgICB0aGlzLnN0YXRpc3RpY3MubWluID0gZWw7XG4gICAgfVxuICB9XG5cbiAgX2FkZFJlY29yZChlbXB0eUVsZW1lbnRzQ291bnQpIHtcbiAgICBpZiAodGhpcy5faW50ZXJtZWRpYXJ5UmVjb3JkICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIHRoaXMuYXJyYXlbdGhpcy5fZmlzcnRRdWV1ZUluZGV4XSA9IHRoaXMuX2ludGVybWVkaWFyeVJlY29yZDtcbiAgICAgIHRoaXMuX2ludGVybWVkaWFyeVJlY29yZCA9IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgbGV0IGN1ckluZGV4SW5BcnJheSA9IHRoaXMuX3VwZGF0ZVJ1bm5pbmdTdGF0aXN0aWNzT25SZW1vdmUoZW1wdHlFbGVtZW50c0NvdW50KTtcbiAgICB0aGlzLl9maXNydFF1ZXVlSW5kZXggPSBjdXJJbmRleEluQXJyYXk7XG4gIH1cblxuICBfY2FsY3VsYXRlRGlmZmVyZW5jZU9mU3VtcyhzdW0xLCBzdW0yLCBjb3VudCkge1xuICAgIGxldCBkaWYgPSBzdW0xIC0gTWF0aC5wb3coc3VtMiwgMikgLyBjb3VudDtcbiAgICByZXR1cm4gZGlmO1xuICB9XG5cbiAgX3VwZGF0ZUludGVybWVkaWFyeVJlY29yZChlbCkge1xuICAgIGlmICh0aGlzLl9pbnRlcm1lZGlhcnlSZWNvcmQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5faW50ZXJtZWRpYXJ5UmVjb3JkID0ge1xuICAgICAgICBjb3VudDogMSxcbiAgICAgICAgc3VtOiBlbCxcbiAgICAgICAgbWF4OiBlbCxcbiAgICAgICAgbWluOiBlbCxcbiAgICAgICAgYXZlcmFnZTogZWwsXG4gICAgICAgIHN1bU9mU3F1YXJlczogTWF0aC5wb3coZWwsIDIpXG4gICAgICB9O1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAodGhpcy5faW50ZXJtZWRpYXJ5UmVjb3JkLm1heCA8IGVsKSB7XG4gICAgICAgIHRoaXMuX2ludGVybWVkaWFyeVJlY29yZC5tYXggPSBlbDtcbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLl9pbnRlcm1lZGlhcnlSZWNvcmQubWluID4gZWwpIHtcbiAgICAgICAgdGhpcy5faW50ZXJtZWRpYXJ5UmVjb3JkLm1pbiA9IGVsO1xuICAgICAgfVxuICAgICAgdGhpcy5faW50ZXJtZWRpYXJ5UmVjb3JkLmNvdW50ICs9IDE7XG4gICAgICB0aGlzLl9pbnRlcm1lZGlhcnlSZWNvcmQuc3VtICs9IGVsO1xuICAgICAgdGhpcy5faW50ZXJtZWRpYXJ5UmVjb3JkLnN1bU9mU3F1YXJlcyArPSBNYXRoLnBvdyhlbCwgMik7XG4gICAgfVxuICB9XG5cbiAgX2ZpbmRNaW4oaW5kZXgpIHtcbiAgICBsZXQgbWluID0gSW5maW5pdHk7XG4gICAgdGhpcy5hcnJheS5mb3JFYWNoKChlbCwgaSkgPT4ge1xuICAgICAgaWYgKGVsICE9PSBudWxsICYmIGVsICE9PSB1bmRlZmluZWQgJiYgZWwubWluICE9PSB1bmRlZmluZWQgJiYgZWwubWluIDwgbWluICYmIGkgIT09IGluZGV4KSB7XG4gICAgICAgIG1pbiA9IGVsLm1pbjtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAobWluID09PSBJbmZpbml0eSkge1xuICAgICAgcmV0dXJuICh0aGlzLl9pbnRlcm1lZGlhcnlSZWNvcmQgIT09IHVuZGVmaW5lZCkgPyB0aGlzLl9pbnRlcm1lZGlhcnlSZWNvcmQubWluIDogdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gbWluO1xuICB9XG5cbiAgX2ZpbmRNYXgoaW5kZXgpIHtcbiAgICBsZXQgbWF4ID0gLUluZmluaXR5O1xuXG4gICAgdGhpcy5hcnJheS5mb3JFYWNoKChlbCwgaSkgPT4ge1xuICAgICAgaWYgKGVsICE9PSBudWxsICYmIGVsICE9PSB1bmRlZmluZWQgJiYgZWwubWF4ICE9PSB1bmRlZmluZWQgJiYgZWwubWF4ID4gbWF4ICYmIGkgIT09IGluZGV4KSB7XG4gICAgICAgIG1heCA9IGVsLm1heDtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBpZiAobWF4ID09PSAtSW5maW5pdHkpIHtcbiAgICAgIHJldHVybiAodGhpcy5faW50ZXJtZWRpYXJ5UmVjb3JkICE9PSB1bmRlZmluZWQpID8gdGhpcy5faW50ZXJtZWRpYXJ5UmVjb3JkLm1heCA6IHVuZGVmaW5lZDtcbiAgICB9XG4gICAgcmV0dXJuIG1heDtcbiAgfVxufVxuIl0sIm5hbWVzIjpbIlJlc2Vydm9pciIsImNoZWNrU3RhdGlzdGljc09uUmVzdG9yZSIsInN0YXRpc3RpY3MiLCJjb3VudCIsInN1bSIsIm1heCIsInVuZGVmaW5lZCIsIm1pbiIsImF2ZXJhZ2UiLCJzdW1PZlNxdWFyZXMiLCJtc2RldiIsInN0ZGRldiIsInB1c2hNZWFzdXJlbWVudCIsImRhdGEiLCJpc0Zpbml0ZSIsIl91cGRhdGVRdWV1ZSIsIl91cGRhdGVJbnRlcm1lZGlhcnlSZWNvcmQiLCJfdXBkYXRlU3RhdGlzdGljc09uQWRkIiwiZ2V0U3RhdGlzdGljcyIsInRvUGxhaW5PYmplY3QiLCJhcnJheSIsInNpemUiLCJfaW50ZXJ2YWwiLCJfcXVldWVFbmRUaW1lIiwiX2Zpc3J0UXVldWVJbmRleCIsIl9pbnRlcm1lZGlhcnlSZWNvcmQiLCJpbnRlcnZhbHNDb3VudCIsIl90YWtlVGltZUludGVydmFsc0NvdW50IiwiZW1wdHlFbGVtZW50c0NvdW50IiwiX3Rha2VFbXB0eUVsZW1lbnRzQWRkQ291bnQiLCJfYWRkUmVjb3JkIiwidGltZU5vdyIsIkRhdGUiLCJub3ciLCJ0aW1lRGlmZiIsInRpbWVJbnRlcnZhbHNDb3VudCIsIk1hdGgiLCJmbG9vciIsIl91cGRhdGVSdW5uaW5nU3RhdGlzdGljc09uUmVtb3ZlIiwicmVtb3ZlQ291bnQiLCJyZW1vdmVFbGVtZW50SW5kZXgiLCJpIiwiX3VwZGF0ZVN0YXRpc3RpY3NPblJlbW92ZSIsInJlbW92ZUVsZW1lbnQiLCJfdXBkYXRlU3RhdGlzdGljc01pbkFuZE1heE9uUmVtb3ZlIiwiZGlmT2ZTdW1zIiwiX2NhbGN1bGF0ZURpZmZlcmVuY2VPZlN1bXMiLCJwYXJzZUZsb2F0Iiwic3FydCIsIl9maW5kTWF4IiwiX2ZpbmRNaW4iLCJlbCIsIl91cGRhdGVTdGF0aXN0aWNzTWluQW5kTWF4T25BZGQiLCJwb3ciLCJjdXJJbmRleEluQXJyYXkiLCJzdW0xIiwic3VtMiIsImRpZiIsImluZGV4IiwiSW5maW5pdHkiLCJmb3JFYWNoIiwiY29uc3RydWN0b3IiLCJvYnNlcnZhdGlvbkludGVy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