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)

229 lines (228 loc) 26.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "default", { enumerable: true, get: function() { return _default; } }); const _avlTree = /*#__PURE__*/ _interop_require_default(require("./avlTree")); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /* jscs:disable */ /* eslint-disable */ const Reservoir = function() { var switchToAlgorithmZConstant = 22; var debug = "none"; /** * Statistical reservoir of a fixed size capable calculating percentile * This reservoir taken from https://www.npmjs.com/package/reservoir * This reservoir has been modified by avl tree (https://www.npmjs.com/package/avl-sorted-list) * Array which contains all data was removed and instead of it add tree */ function _Reservoir(reservoirSize, storagePeriodInMilliseconds, randomNumberGen) { let interval = storagePeriodInMilliseconds; var rng = randomNumberGen || Math.random; var reservoirSize = Math.max(1, Math.floor(reservoirSize) >> 0 || 1); var totalItemCount = 0; var lastDeletedIndex = -1; var numToSkip = -1; var currentAlgorithm = algorithmX; var switchThreshold = switchToAlgorithmZConstant * reservoirSize; if (debug === "R") { currentAlgorithm = algorithmR; } else if (debug === "X") { switchThreshold = Infinity; } else if (debug === "Z") { currentAlgorithm = algorithmZ; } var algorithmXCount = 0; var W = Math.exp(-Math.log(rng()) / reservoirSize); var evictNext = null; let indexTree = new _avlTree.default(function(a, b) { return a.index - b.index; }); let valueTree = new _avlTree.default(function(a, b) { return a - b; }); let initialIndex = 0; indexTree.removeOldRecords = function() { while(true){ let element = this.at(0); if (element !== null && Date.now() > element.time + interval) { this.removeAt(0); var deletedIndexDiff = element.index - lastDeletedIndex; lastDeletedIndex = element.index; valueTree.remove(element.data); totalItemCount -= deletedIndexDiff; algorithmXCount = Math.max(0, algorithmXCount - deletedIndexDiff); } else { break; } } }; indexTree.getPercentile = function() { let percent = arguments[0]; this.removeOldRecords(); const index = (this.size() - 1) * percent / 100; const lower = Math.floor(index); const fractionPart = index - lower; let percentile = valueTree.at(lower); if (fractionPart > 0) { percentile += fractionPart * (valueTree.at(lower + 1) - valueTree.at(lower)); } return parseFloat(percentile); }; indexTree.pushSome = function() { let len = Math.min(this.size(), reservoirSize); for(var i = 0; i < arguments.length; i++){ this.removeOldRecords(); var value = { index: initialIndex, time: Date.now(), data: arguments[i] }; addSample.call(this, value); initialIndex++; } return len; }; indexTree.fromPlainObject = function() { let len = Math.min(this.size(), reservoirSize); for(var i = 0; i < arguments.length; i++){ var value = { index: arguments[i].index, time: arguments[i].time, data: arguments[i].data }; addSample.call(this, value); initialIndex++; } return len; }; var addSample = function(sample) { if (this.size() < reservoirSize) { this.insert(sample); valueTree.insert(sample.data); } else { if (numToSkip < 0) { numToSkip = currentAlgorithm(); } if (numToSkip === 0) { replaceRandomSample(sample, this); } numToSkip--; } totalItemCount++; return this; }; function replaceRandomSample(sample, reservoir) { var randomIndex; if (evictNext !== null) { randomIndex = evictNext; evictNext = null; } else { randomIndex = Math.floor(rng() * reservoirSize); } let value = reservoir.at(randomIndex); reservoir.removeAt(randomIndex); valueTree.remove(value.data); valueTree.insert(sample.data); reservoir.insert(sample); } /** * "Algorithm R" * Selects random elements from an unknown-length input. * Has a time-complexity of: O(N) * Number of random numbers required: * N - n * Where: * n = the size of the reservoir * N = the size of the input */ function algorithmR() { var localItemCount = totalItemCount + 1, randomValue = Math.floor(rng() * localItemCount), toSkip = 0; while(randomValue >= reservoirSize){ toSkip++; localItemCount++; randomValue = Math.floor(rng() * localItemCount); } evictNext = randomValue; return toSkip; } /** "Algorithm X" * Selects random elements from an unknown-length input. * Has a time-complexity of: O(N) * Number of random numbers required: * 2 * n * ln( N / n ) * Where: * n = the size of the reservoir * N = the size of the input */ function algorithmX() { var localItemCount = totalItemCount, randomValue = rng(), toSkip = 0, quotient; if (totalItemCount <= switchThreshold) { localItemCount++; algorithmXCount++; quotient = algorithmXCount / localItemCount; while(quotient > randomValue){ toSkip++; localItemCount++; algorithmXCount++; quotient = quotient * algorithmXCount / localItemCount; } return toSkip; } else { currentAlgorithm = algorithmZ; return currentAlgorithm(); } } /** "Algorithm Z" * Selects random elements from an unknown-length input. * Has a time-complexity of: * O(n(1 + log (N / n))) * Number of random numbers required: * 2 * n * ln( N / n ) * Where: * n = the size of the reservoir * N = the size of the input */ function algorithmZ() { var term = totalItemCount - reservoirSize + 1, denom, numer, numer_lim; while(true){ var randomValue = rng(); var x = totalItemCount * (W - 1); var toSkip = Math.floor(x); var subterm = (totalItemCount + 1) / term; subterm *= subterm; var termSkip = term + toSkip; var lhs = Math.exp(Math.log(randomValue * subterm * termSkip / (totalItemCount + x)) / reservoirSize); var rhs = (totalItemCount + x) / termSkip * term / totalItemCount; if (lhs <= rhs) { W = rhs / lhs; break; } var y = randomValue * (totalItemCount + 1) / term * (totalItemCount + toSkip + 1) / (totalItemCount + x); if (reservoirSize < toSkip) { denom = totalItemCount; numer_lim = term + toSkip; } else { denom = totalItemCount - reservoirSize + toSkip; numer_lim = totalItemCount + 1; } for(numer = totalItemCount + toSkip; numer >= numer_lim; numer--){ y = y * numer / denom; denom--; } W = Math.exp(-Math.log(rng()) / reservoirSize); if (Math.exp(Math.log(y) / reservoirSize) <= (totalItemCount + x) / totalItemCount) { break; } } return toSkip; } return indexTree; } return _Reservoir; }(); const _default = Reservoir; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjxhbm9uPiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmltcG9ydCBBdmxUcmVlIGZyb20gJy4vYXZsVHJlZSc7XG5cbi8qIGpzY3M6ZGlzYWJsZSAqL1xuLyogZXNsaW50LWRpc2FibGUgKi9cbmNvbnN0IFJlc2Vydm9pciA9IChmdW5jdGlvbiAoKSB7XG5cbiAgdmFyIHN3aXRjaFRvQWxnb3JpdGhtWkNvbnN0YW50ID0gMjI7XG4gIHZhciBkZWJ1ZyA9ICdub25lJztcblxuICAvKipcbiAgICogU3RhdGlzdGljYWwgcmVzZXJ2b2lyIG9mIGEgZml4ZWQgc2l6ZSBjYXBhYmxlIGNhbGN1bGF0aW5nIHBlcmNlbnRpbGVcbiAgICogVGhpcyByZXNlcnZvaXIgdGFrZW4gZnJvbSBodHRwczovL3d3dy5ucG1qcy5jb20vcGFja2FnZS9yZXNlcnZvaXJcbiAgICogVGhpcyByZXNlcnZvaXIgaGFzIGJlZW4gbW9kaWZpZWQgYnkgYXZsIHRyZWUgKGh0dHBzOi8vd3d3Lm5wbWpzLmNvbS9wYWNrYWdlL2F2bC1zb3J0ZWQtbGlzdClcbiAgICogQXJyYXkgd2hpY2ggY29udGFpbnMgYWxsIGRhdGEgd2FzIHJlbW92ZWQgYW5kIGluc3RlYWQgb2YgaXQgYWRkIHRyZWVcbiAgICovXG4gIGZ1bmN0aW9uIF9SZXNlcnZvaXIocmVzZXJ2b2lyU2l6ZSwgc3RvcmFnZVBlcmlvZEluTWlsbGlzZWNvbmRzLCByYW5kb21OdW1iZXJHZW4pIHtcbiAgICBsZXQgaW50ZXJ2YWwgPSBzdG9yYWdlUGVyaW9kSW5NaWxsaXNlY29uZHM7XG4gICAgdmFyIHJuZyA9IHJhbmRvbU51bWJlckdlbiB8fCBNYXRoLnJhbmRvbTtcbiAgICB2YXIgcmVzZXJ2b2lyU2l6ZSA9IE1hdGgubWF4KDEsIChNYXRoLmZsb29yKHJlc2Vydm9pclNpemUpID4+IDApIHx8IDEpO1xuICAgIHZhciB0b3RhbEl0ZW1Db3VudCA9IDA7XG4gICAgdmFyIGxhc3REZWxldGVkSW5kZXggPSAtMTtcbiAgICB2YXIgbnVtVG9Ta2lwID0gLTE7XG4gICAgdmFyIGN1cnJlbnRBbGdvcml0aG0gPSBhbGdvcml0aG1YO1xuICAgIHZhciBzd2l0Y2hUaHJlc2hvbGQgPVxuICAgICAgc3dpdGNoVG9BbGdvcml0aG1aQ29uc3RhbnQgKiByZXNlcnZvaXJTaXplO1xuXG4gICAgaWYgKGRlYnVnID09PSAnUicpIHtcbiAgICAgIGN1cnJlbnRBbGdvcml0aG0gPSBhbGdvcml0aG1SO1xuICAgIH0gZWxzZSBpZiAoZGVidWcgPT09ICdYJykge1xuICAgICAgc3dpdGNoVGhyZXNob2xkID0gSW5maW5pdHk7XG4gICAgfSBlbHNlIGlmIChkZWJ1ZyA9PT0gJ1onKSB7XG4gICAgICBjdXJyZW50QWxnb3JpdGhtID0gYWxnb3JpdGhtWjtcbiAgICB9XG5cbiAgICB2YXIgYWxnb3JpdGhtWENvdW50ID0gMDtcbiAgICB2YXIgVyA9IE1hdGguZXhwKC1NYXRoLmxvZyhybmcoKSkgLyByZXNlcnZvaXJTaXplKTtcbiAgICB2YXIgZXZpY3ROZXh0ID0gbnVsbDtcblxuICAgIGxldCBpbmRleFRyZWUgPSBuZXcgQXZsVHJlZShmdW5jdGlvbiAoYSwgYikge1xuICAgICAgcmV0dXJuIGEuaW5kZXggLSBiLmluZGV4O1xuICAgIH0pO1xuXG4gICAgbGV0IHZhbHVlVHJlZSA9IG5ldyBBdmxUcmVlKGZ1bmN0aW9uIChhLCBiKSB7XG4gICAgICByZXR1cm4gYSAtIGI7XG4gICAgfSk7XG4gICAgbGV0IGluaXRpYWxJbmRleCA9IDA7XG5cbiAgICBpbmRleFRyZWUucmVtb3ZlT2xkUmVjb3JkcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIGxldCBlbGVtZW50ID0gdGhpcy5hdCgwKTtcbiAgICAgICAgaWYgKGVsZW1lbnQgIT09IG51bGwgJiYgRGF0ZS5ub3coKSA+IGVsZW1lbnQudGltZSArIGludGVydmFsKSB7XG4gICAgICAgICAgdGhpcy5yZW1vdmVBdCgwKTtcbiAgICAgICAgICB2YXIgZGVsZXRlZEluZGV4RGlmZiA9IGVsZW1lbnQuaW5kZXggLSBsYXN0RGVsZXRlZEluZGV4O1xuICAgICAgICAgIGxhc3REZWxldGVkSW5kZXggPSBlbGVtZW50LmluZGV4O1xuICAgICAgICAgIHZhbHVlVHJlZS5yZW1vdmUoZWxlbWVudC5kYXRhKTtcbiAgICAgICAgICB0b3RhbEl0ZW1Db3VudCAtPSBkZWxldGVkSW5kZXhEaWZmO1xuICAgICAgICAgIGFsZ29yaXRobVhDb3VudCA9IE1hdGgubWF4KDAsIGFsZ29yaXRobVhDb3VudCAtIGRlbGV0ZWRJbmRleERpZmYpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfTtcblxuICAgIGluZGV4VHJlZS5nZXRQZXJjZW50aWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IHBlcmNlbnQgPSBhcmd1bWVudHNbMF07XG4gICAgICB0aGlzLnJlbW92ZU9sZFJlY29yZHMoKTtcbiAgICAgIGNvbnN0IGluZGV4ID0gKHRoaXMuc2l6ZSgpIC0gMSkgKiBwZXJjZW50IC8gMTAwO1xuICAgICAgY29uc3QgbG93ZXIgPSBNYXRoLmZsb29yKGluZGV4KTtcbiAgICAgIGNvbnN0IGZyYWN0aW9uUGFydCA9IGluZGV4IC0gbG93ZXI7XG4gICAgICBsZXQgcGVyY2VudGlsZSA9IHZhbHVlVHJlZS5hdChsb3dlcik7XG4gICAgICBpZiAoZnJhY3Rpb25QYXJ0ID4gMCkge1xuICAgICAgICBwZXJjZW50aWxlICs9IGZyYWN0aW9uUGFydCAqICh2YWx1ZVRyZWUuYXQobG93ZXIgKyAxKSAtIHZhbHVlVHJlZS5hdChsb3dlcikpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHBhcnNlRmxvYXQocGVyY2VudGlsZSk7XG4gICAgfTtcblxuICAgIGluZGV4VHJlZS5wdXNoU29tZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGxldCBsZW4gPSBNYXRoLm1pbih0aGlzLnNpemUoKSwgcmVzZXJ2b2lyU2l6ZSk7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICB0aGlzLnJlbW92ZU9sZFJlY29yZHMoKTtcbiAgICAgICAgdmFyIHZhbHVlID0ge2luZGV4OiBpbml0aWFsSW5kZXgsIHRpbWU6IERhdGUubm93KCksIGRhdGE6IGFyZ3VtZW50c1tpXX07XG4gICAgICAgIGFkZFNhbXBsZS5jYWxsKHRoaXMsIHZhbHVlKTtcbiAgICAgICAgaW5pdGlhbEluZGV4Kys7XG4gICAgICB9XG4gICAgICByZXR1cm4gbGVuO1xuICAgIH07XG5cbiAgICBpbmRleFRyZWUuZnJvbVBsYWluT2JqZWN0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgbGV0IGxlbiA9IE1hdGgubWluKHRoaXMuc2l6ZSgpLCByZXNlcnZvaXJTaXplKTtcbiAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIHZhciB2YWx1ZSA9IHtpbmRleDogYXJndW1lbnRzW2ldLmluZGV4LCB0aW1lOiBhcmd1bWVudHNbaV0udGltZSwgZGF0YTogYXJndW1lbnRzW2ldLmRhdGF9O1xuICAgICAgICBhZGRTYW1wbGUuY2FsbCh0aGlzLCB2YWx1ZSk7XG4gICAgICAgIGluaXRpYWxJbmRleCsrO1xuICAgICAgfVxuICAgICAgcmV0dXJuIGxlbjtcbiAgICB9O1xuXG4gICAgdmFyIGFkZFNhbXBsZSA9IGZ1bmN0aW9uIChzYW1wbGUpIHtcbiAgICAgIGlmICh0aGlzLnNpemUoKSA8IHJlc2Vydm9pclNpemUpIHtcbiAgICAgICAgdGhpcy5pbnNlcnQoc2FtcGxlKTtcbiAgICAgICAgdmFsdWVUcmVlLmluc2VydChzYW1wbGUuZGF0YSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAobnVtVG9Ta2lwIDwgMCkge1xuICAgICAgICAgIG51bVRvU2tpcCA9IGN1cnJlbnRBbGdvcml0aG0oKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAobnVtVG9Ta2lwID09PSAwKSB7XG4gICAgICAgICAgcmVwbGFjZVJhbmRvbVNhbXBsZShzYW1wbGUsIHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIG51bVRvU2tpcC0tO1xuICAgICAgfVxuICAgICAgdG90YWxJdGVtQ291bnQrKztcbiAgICAgIHJldHVybiB0aGlzO1xuICAgIH07XG5cbiAgICBmdW5jdGlvbiByZXBsYWNlUmFuZG9tU2FtcGxlKHNhbXBsZSwgcmVzZXJ2b2lyKSB7XG4gICAgICB2YXIgcmFuZG9tSW5kZXg7XG4gICAgICBpZiAoZXZpY3ROZXh0ICE9PSBudWxsKSB7XG4gICAgICAgIHJhbmRvbUluZGV4ID0gZXZpY3ROZXh0O1xuICAgICAgICBldmljdE5leHQgPSBudWxsO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmFuZG9tSW5kZXggPSBNYXRoLmZsb29yKHJuZygpICogcmVzZXJ2b2lyU2l6ZSk7XG4gICAgICB9XG4gICAgICBsZXQgdmFsdWUgPSByZXNlcnZvaXIuYXQocmFuZG9tSW5kZXgpO1xuICAgICAgcmVzZXJ2b2lyLnJlbW92ZUF0KHJhbmRvbUluZGV4KTtcbiAgICAgIHZhbHVlVHJlZS5yZW1vdmUodmFsdWUuZGF0YSk7XG4gICAgICB2YWx1ZVRyZWUuaW5zZXJ0KHNhbXBsZS5kYXRhKTtcbiAgICAgIHJlc2Vydm9pci5pbnNlcnQoc2FtcGxlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBcIkFsZ29yaXRobSBSXCJcbiAgICAgKiBTZWxlY3RzIHJhbmRvbSBlbGVtZW50cyBmcm9tIGFuIHVua25vd24tbGVuZ3RoIGlucHV0LlxuICAgICAqIEhhcyBhIHRpbWUtY29tcGxleGl0eSBvZjogTyhOKVxuICAgICAqIE51bWJlciBvZiByYW5kb20gbnVtYmVycyByZXF1aXJlZDpcbiAgICAgKiBOIC0gblxuICAgICAqIFdoZXJlOlxuICAgICAqIG4gPSB0aGUgc2l6ZSBvZiB0aGUgcmVzZXJ2b2lyXG4gICAgICogTiA9IHRoZSBzaXplIG9mIHRoZSBpbnB1dFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFsZ29yaXRobVIoKSB7XG4gICAgICB2YXIgbG9jYWxJdGVtQ291bnQgPSB0b3RhbEl0ZW1Db3VudCArIDEsXG4gICAgICAgIHJhbmRvbVZhbHVlID0gTWF0aC5mbG9vcihybmcoKSAqIGxvY2FsSXRlbUNvdW50KSxcbiAgICAgICAgdG9Ta2lwID0gMDtcblxuICAgICAgd2hpbGUgKHJhbmRvbVZhbHVlID49IHJlc2Vydm9pclNpemUpIHtcbiAgICAgICAgdG9Ta2lwKys7XG4gICAgICAgIGxvY2FsSXRlbUNvdW50Kys7XG4gICAgICAgIHJhbmRvbVZhbHVlID0gTWF0aC5mbG9vcihybmcoKSAqIGxvY2FsSXRlbUNvdW50KTtcbiAgICAgIH1cbiAgICAgIGV2aWN0TmV4dCA9IHJhbmRvbVZhbHVlO1xuICAgICAgcmV0dXJuIHRvU2tpcDtcbiAgICB9XG5cbiAgICAvKiogXCJBbGdvcml0aG0gWFwiXG4gICAgICogU2VsZWN0cyByYW5kb20gZWxlbWVudHMgZnJvbSBhbiB1bmtub3duLWxlbmd0aCBpbnB1dC5cbiAgICAgKiBIYXMgYSB0aW1lLWNvbXBsZXhpdHkgb2Y6IE8oTilcbiAgICAgKiBOdW1iZXIgb2YgcmFuZG9tIG51bWJlcnMgcmVxdWlyZWQ6XG4gICAgICogIDIgKiBuICogbG4oIE4gLyBuIClcbiAgICAgKiBXaGVyZTpcbiAgICAgKiAgbiA9IHRoZSBzaXplIG9mIHRoZSByZXNlcnZvaXJcbiAgICAgKiAgTiA9IHRoZSBzaXplIG9mIHRoZSBpbnB1dFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGFsZ29yaXRobVgoKSB7XG4gICAgICB2YXIgbG9jYWxJdGVtQ291bnQgPSB0b3RhbEl0ZW1Db3VudCxcbiAgICAgICAgcmFuZG9tVmFsdWUgPSBybmcoKSxcbiAgICAgICAgdG9Ta2lwID0gMCxcbiAgICAgICAgcXVvdGllbnQ7XG5cbiAgICAgIGlmICh0b3RhbEl0ZW1Db3VudCA8PSBzd2l0Y2hUaHJlc2hvbGQpIHtcbiAgICAgICAgbG9jYWxJdGVtQ291bnQrKztcbiAgICAgICAgYWxnb3JpdGhtWENvdW50Kys7XG4gICAgICAgIHF1b3RpZW50ID0gYWxnb3JpdGhtWENvdW50IC8gbG9jYWxJdGVtQ291bnQ7XG5cbiAgICAgICAgd2hpbGUgKHF1b3RpZW50ID4gcmFuZG9tVmFsdWUpIHtcbiAgICAgICAgICB0b1NraXArKztcbiAgICAgICAgICBsb2NhbEl0ZW1Db3VudCsrO1xuICAgICAgICAgIGFsZ29yaXRobVhDb3VudCsrO1xuICAgICAgICAgIHF1b3RpZW50ID0gKHF1b3RpZW50ICogYWxnb3JpdGhtWENvdW50KSAvIGxvY2FsSXRlbUNvdW50O1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0b1NraXA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjdXJyZW50QWxnb3JpdGhtID0gYWxnb3JpdGhtWjtcbiAgICAgICAgcmV0dXJuIGN1cnJlbnRBbGdvcml0aG0oKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvKiogXCJBbGdvcml0aG0gWlwiXG4gICAgICogU2VsZWN0cyByYW5kb20gZWxlbWVudHMgZnJvbSBhbiB1bmtub3duLWxlbmd0aCBpbnB1dC5cbiAgICAgKiBIYXMgYSB0aW1lLWNvbXBsZXhpdHkgb2Y6XG4gICAgICogIE8obigxICsgbG9nIChOIC8gbikpKVxuICAgICAqIE51bWJlciBvZiByYW5kb20gbnVtYmVycyByZXF1aXJlZDpcbiAgICAgKiAgMiAqIG4gKiBsbiggTiAvIG4gKVxuICAgICAqIFdoZXJlOlxuICAgICAqICBuID0gdGhlIHNpemUgb2YgdGhlIHJlc2Vydm9pclxuICAgICAqICBOID0gdGhlIHNpemUgb2YgdGhlIGlucHV0XG4gICAgICovXG4gICAgZnVuY3Rpb24gYWxnb3JpdGhtWigpIHtcbiAgICAgIHZhciB0ZXJtID0gdG90YWxJdGVtQ291bnQgLSByZXNlcnZvaXJTaXplICsgMSxcbiAgICAgICAgZGVub20sXG4gICAgICAgIG51bWVyLFxuICAgICAgICBudW1lcl9saW07XG5cbiAgICAgIHdoaWxlICh0cnVlKSB7XG4gICAgICAgIHZhciByYW5kb21WYWx1ZSA9IHJuZygpO1xuICAgICAgICB2YXIgeCA9IHRvdGFsSXRlbUNvdW50ICogKFcgLSAxKTtcbiAgICAgICAgdmFyIHRvU2tpcCA9IE1hdGguZmxvb3IoeCk7XG5cbiAgICAgICAgdmFyIHN1YnRlcm0gPSAoKHRvdGFsSXRlbUNvdW50ICsgMSkgLyB0ZXJtKTtcbiAgICAgICAgc3VidGVybSAqPSBzdWJ0ZXJtO1xuICAgICAgICB2YXIgdGVybVNraXAgPSB0ZXJtICsgdG9Ta2lwO1xuICAgICAgICB2YXIgbGhzID0gTWF0aC5leHAoTWF0aC5sb2coKChyYW5kb21WYWx1ZSAqIHN1YnRlcm0pICogdGVybVNraXApIC8gKHRvdGFsSXRlbUNvdW50ICsgeCkpIC8gcmVzZXJ2b2lyU2l6ZSk7XG4gICAgICAgIHZhciByaHMgPSAoKCh0b3RhbEl0ZW1Db3VudCArIHgpIC8gdGVybVNraXApICogdGVybSkgLyB0b3RhbEl0ZW1Db3VudDtcblxuICAgICAgICBpZiAobGhzIDw9IHJocykge1xuICAgICAgICAgIFcgPSByaHMgLyBsaHM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgeSA9ICgoKHJhbmRvbVZhbHVlICogKHRvdGFsSXRlbUNvdW50ICsgMSkpIC8gdGVybSkgKiAodG90YWxJdGVtQ291bnQgKyB0b1NraXAgKyAxKSkgLyAodG90YWxJdGVtQ291bnQgKyB4KTtcblxuICAgICAgICBpZiAocmVzZXJ2b2lyU2l6ZSA8IHRvU2tpcCkge1xuICAgICAgICAgIGRlbm9tID0gdG90YWxJdGVtQ291bnQ7XG4gICAgICAgICAgbnVtZXJfbGltID0gdGVybSArIHRvU2tpcDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkZW5vbSA9IHRvdGFsSXRlbUNvdW50IC0gcmVzZXJ2b2lyU2l6ZSArIHRvU2tpcDtcbiAgICAgICAgICBudW1lcl9saW0gPSB0b3RhbEl0ZW1Db3VudCArIDE7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKG51bWVyID0gdG90YWxJdGVtQ291bnQgKyB0b1NraXA7IG51bWVyID49IG51bWVyX2xpbTsgbnVtZXItLSkge1xuICAgICAgICAgIHkgPSAoeSAqIG51bWVyKSAvIGRlbm9tO1xuICAgICAgICAgIGRlbm9tLS07XG4gICAgICAgIH1cblxuICAgICAgICBXID0gTWF0aC5leHAoLU1hdGgubG9nKHJuZygpKSAvIHJlc2Vydm9pclNpemUpO1xuXG4gICAgICAgIGlmIChNYXRoLmV4cChNYXRoLmxvZyh5KSAvIHJlc2Vydm9pclNpemUpIDw9ICh0b3RhbEl0ZW1Db3VudCArIHgpIC8gdG90YWxJdGVtQ291bnQpIHtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRvU2tpcDtcbiAgICB9XG4gICAgcmV0dXJuIGluZGV4VHJlZTtcbiAgfVxuICByZXR1cm4gX1Jlc2Vydm9pcjtcbn0oKSk7XG5cbmV4cG9ydCBkZWZhdWx0IFJlc2Vydm9pcjtcbiJdLCJuYW1lcyI6WyJSZXNlcnZvaXIiLCJzd2l0Y2hUb0FsZ29yaXRobVpDb25zdGFudCIsImRlYnVnIiwiX1Jlc2Vydm9pciIsInJlc2Vydm9pclNpemUiLCJzdG9yYWdlUGVyaW9kSW5NaWxsaXNlY29uZHMiLCJyYW5kb21OdW1iZXJHZW4iLCJpbnRlcnZhbCIsInJuZyIsIk1hdGgiLCJyYW5kb20iLCJtYXgiLCJmbG9vciIsInRvdGFsSXRlbUNvdW50IiwibGFzdERlbGV0ZWRJbmRleCIsIm51bVRvU2tpcCIsImN1cnJlbnRBbGdvcml0aG0iLCJhbGdvcml0aG1YIiwic3dpdGNoVGhyZXNob2xkIiwiYWxnb3JpdGhtUiIsIkluZmluaXR5IiwiYWxnb3JpdGhtWiIsImFsZ29yaXRobVhDb3VudCIsIlciLCJleHAiLCJsb2ciLCJldmljdE5leHQiLCJpbmRleFRyZWUiLCJBdmxUcmVlIiwiYSIsImIiLCJpbmRleCIsInZhbHVlVHJlZSIsImluaXRpYWxJbmRleCIsInJlbW92ZU9sZFJlY29yZHMiLCJlbGVtZW50IiwiYXQiLCJEYXRlIiwibm93IiwidGltZSIsInJlbW92ZUF0IiwiZGVsZXRlZEluZGV4RGlmZiIsInJlbW92ZSIsImRhdGEiLCJnZXRQZXJjZW50aWxlIiwicGVyY2VudCIsImFyZ3VtZW50cyIsInNpemUiLCJsb3dlciIsImZyYWN0aW9uUGFydCIsInBlcmNlbnRpbGUiLCJwYXJzZUZsb2F0IiwicHVzaFNvbWUiLCJsZW4iLCJtaW4iLCJpIiwibGVuZ3RoIiwidmFsdWUiLCJhZGRTYW1wbGUiLCJjYWxsIiwiZnJvbVBsYWluT2JqZWN0Iiwic2FtcGxlIiwiaW5zZXJ0IiwicmVwbGFjZVJhbmRvbVNhbXBsZSIsInJlc2Vydm9pciIsInJhbmRvbUluZGV4IiwibG9jYWxJdGVtQ291bnQiLCJyYW5kb21WYWx1ZSIsInRvU2tpcCIsInF1b3RpZW50IiwidGVybSIsImRlbm9tIiwibnVtZXIiLCJudW1lcl9saW0iLCJ4Iiwic3VidGVybSIsInRlcm1Ta2lwIiwibGhzIiwicmhzIiwieSJdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7K0JBd1BBOzs7ZUFBQTs7O2dFQXRQb0I7Ozs7OztBQUVwQixnQkFBZ0IsR0FDaEIsa0JBQWtCLEdBQ2xCLE1BQU1BLFlBQWE7SUFFakIsSUFBSUMsNkJBQTZCO0lBQ2pDLElBQUlDLFFBQVE7SUFFWjs7Ozs7R0FLQyxHQUNELFNBQVNDLFdBQVdDLGFBQWEsRUFBRUMsMkJBQTJCLEVBQUVDLGVBQWU7UUFDN0UsSUFBSUMsV0FBV0Y7UUFDZixJQUFJRyxNQUFNRixtQkFBbUJHLEtBQUtDLE1BQU07UUFDeEMsSUFBSU4sZ0JBQWdCSyxLQUFLRSxHQUFHLENBQUMsR0FBRyxBQUFDRixLQUFLRyxLQUFLLENBQUNSLGtCQUFrQixLQUFNO1FBQ3BFLElBQUlTLGlCQUFpQjtRQUNyQixJQUFJQyxtQkFBbUIsQ0FBQztRQUN4QixJQUFJQyxZQUFZLENBQUM7UUFDakIsSUFBSUMsbUJBQW1CQztRQUN2QixJQUFJQyxrQkFDRmpCLDZCQUE2Qkc7UUFFL0IsSUFBSUYsVUFBVSxLQUFLO1lBQ2pC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