UNPKG

faastjs

Version:

Serverless batch computing made simple.

291 lines 32.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SmallestN = exports.MaxHeap = exports.defined = exports.keysOf = exports.f2 = exports.f1 = exports.KB = exports.MB = exports.GB = exports.uuidv4Pattern = exports.roundTo100ms = exports.hasExpired = exports.computeHttpResponseBytes = exports.objectSize = exports.sum = exports.chomp = exports.streamToBuffer = exports.sleep = exports.ExponentiallyDecayingAverageValue = exports.Statistics = void 0; /** * Incrementally updated statistics on a set of values. * @public */ class Statistics { /** * Incrementally track mean, stdev, min, max, of a sequence of values. * @param printFixedPrecision - The number of decimal places to print in * {@link Statistics.toString}. */ constructor( /** The number of decimal places to print in {@link Statistics.toString} */ printFixedPrecision = 1) { this.printFixedPrecision = printFixedPrecision; /** Number of values observed. */ this.samples = 0; /** The maximum value observed. Initialized to `Number.NEGATIVE_INFINITY`. */ this.max = Number.NEGATIVE_INFINITY; /** The minimum value observed. Initialized to `Number.POSITIVE_INFINITY`. */ this.min = Number.POSITIVE_INFINITY; /** The variance of the values observed. */ this.variance = 0; /** The standard deviation of the values observed. */ this.stdev = 0; /** The mean (average) of the values observed. */ this.mean = NaN; } /** @internal */ clone() { const rv = new Statistics(this.printFixedPrecision); return Object.assign(rv, this); } /** * Update statistics with a new value in the sequence. */ update(value) { if (value === undefined) { return; } let previousMean = this.mean; // https://math.stackexchange.com/questions/374881/recursive-formula-for-variance let previousVariance = this.variance; if (this.samples === 0) { previousMean = 0; previousVariance = 0; } this.samples++; this.mean = previousMean + (value - previousMean) / this.samples; this.variance = ((previousVariance + (previousMean - value) ** 2 / this.samples) * (this.samples - 1)) / this.samples; this.stdev = Math.sqrt(this.variance); if (value > this.max) { this.max = value; } if (value < this.min) { this.min = value; } } /** * Print the mean of the observations seen, with the precision specified in * the constructor. */ toString() { return `${this.mean.toFixed(this.printFixedPrecision)}`; } } exports.Statistics = Statistics; class ExponentiallyDecayingAverageValue { constructor(smoothingFactor) { this.smoothingFactor = smoothingFactor; this.samples = 0; this.value = 0; } update(n) { // tslint:disable-next-line:prefer-conditional-expression if (this.samples++ === 0) { this.value = n; } else { this.value = this.smoothingFactor * n + (1 - this.smoothingFactor) * this.value; } } toString() { return this.value; } } exports.ExponentiallyDecayingAverageValue = ExponentiallyDecayingAverageValue; function sleep(ms, cancel = new Promise(() => { })) { let id; cancel.then(_ => clearTimeout(id)).catch(_ => clearTimeout(id)); return Promise.race([new Promise(resolve => (id = setTimeout(resolve, ms))), cancel]); } exports.sleep = sleep; function streamToBuffer(s) { return new Promise((resolve, reject) => { const buffers = []; s.on("error", reject); s.on("data", (data) => buffers.push(data)); s.on("end", () => resolve(Buffer.concat(buffers))); }); } exports.streamToBuffer = streamToBuffer; function chomp(s) { if (s.length > 0 && s[s.length - 1] === "\n") { s = s.slice(0, s.length - 1); } return s; } exports.chomp = chomp; const sum = (a) => a.reduce((total, n) => total + n, 0); exports.sum = sum; function objectSize(obj) { if (!obj) { return 0; } return (0, exports.sum)(Object.keys(obj).map(key => key.length + obj[key].length)); } exports.objectSize = objectSize; function computeHttpResponseBytes(headers, opts = { httpHeaders: true, min: 0 }) { const headerKeys = Object.keys(headers); let contentLength = 0; for (const key of headerKeys) { if (key.match(/^content-length$/i)) { contentLength = Number(headers[key]); break; } } if (!opts.httpHeaders) { return Math.max(contentLength, opts.min); } const headerLength = objectSize(headers) + headerKeys.length * ": ".length; const otherLength = 13; return Math.max(contentLength + headerLength + otherLength, opts.min); } exports.computeHttpResponseBytes = computeHttpResponseBytes; function hasExpired(date, retentionInDays) { if (retentionInDays <= 0) { return true; } const timestamp = typeof date === "string" ? Date.parse(date) : date || 0; return timestamp < Date.now() - retentionInDays * 24 * 60 * 60 * 1000; } exports.hasExpired = hasExpired; function roundTo100ms(n) { return Math.round(n / 100) * 100; } exports.roundTo100ms = roundTo100ms; exports.uuidv4Pattern = "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}"; exports.GB = 2 ** 30; exports.MB = 2 ** 20; exports.KB = 2 ** 10; function f1(n) { return n.toFixed(1); } exports.f1 = f1; function f2(n) { return n.toFixed(2); } exports.f2 = f2; function keysOf(obj) { return Object.keys(obj); } exports.keysOf = keysOf; function defined(arg) { return !!arg; } exports.defined = defined; class MaxHeap { constructor() { this._heap = []; } get size() { return this._heap.length; } clear() { this._heap = []; } peekMax() { return this._heap[0]; } insert(value) { const h = this._heap; h.push(value); let i = h.length - 1; const parentOf = (n) => Math.floor((n - 1) / 2); let parent = parentOf(i); while (parent >= 0 && h[i] > h[parent]) { const tmp = h[parent]; h[parent] = h[i]; h[i] = tmp; i = parent; parent = parentOf(i); } } extractMax() { const h = this._heap; if (h.length === 0) { throw new Error("extractMax called on empty heap"); } let i = 0; const rv = h[0]; h[0] = h[h.length - 1]; h.pop(); while (i < h.length) { const [left, right] = [i * 2 + 1, i * 2 + 2]; let maybe; if (h[i] < h[left] && !(h[right] > h[left])) { maybe = left; } else if (h[i] < h[right]) { maybe = right; } if (maybe === undefined) { break; } const [iValue, mValue] = [h[i], h[maybe]]; h[i] = mValue; h[maybe] = iValue; i = maybe; } return rv; } [Symbol.iterator]() { return this._heap[Symbol.iterator](); } } exports.MaxHeap = MaxHeap; class SmallestN { constructor(_size) { this._size = _size; this._heap = new MaxHeap(); this._map = []; } update(key, value) { if (this._heap.size < this._size) { this._heap.insert(key); this._map.push([key, value]); return; } if (key >= this._heap.peekMax()) { return; } this._heap.insert(key); this._map.push([key, value]); this.shrink(); } shrink() { const max = this._heap.extractMax(); let idx = this._map.length; while (--idx >= 0) { if (this._map[idx][0] === max) { break; } } if (idx === -1) { throw new Error(`SmallestN: could not find entry for key ${max}`); } this._map.splice(idx, 1); } [Symbol.iterator]() { return this._map[Symbol.iterator](); } entries() { return this._map[Symbol.iterator]; } keys() { return [...this._heap]; } get size() { return this._size; } clear() { this._heap.clear(); this._map = []; } setSize(newSize) { while (this._size > newSize) { this.shrink(); this._size--; } this._size = newSize; } } exports.SmallestN = SmallestN; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NoYXJlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7O0dBR0c7QUFDSCxNQUFhLFVBQVU7SUFjbkI7Ozs7T0FJRztJQUNIO0lBQ0ksMkVBQTJFO0lBQ2pFLHNCQUE4QixDQUFDO1FBQS9CLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBWTtRQXBCN0MsaUNBQWlDO1FBQ2pDLFlBQU8sR0FBRyxDQUFDLENBQUM7UUFDWiw2RUFBNkU7UUFDN0UsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQiw2RUFBNkU7UUFDN0UsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQiwyQ0FBMkM7UUFDM0MsYUFBUSxHQUFHLENBQUMsQ0FBQztRQUNiLHFEQUFxRDtRQUNyRCxVQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsaURBQWlEO1FBQ2pELFNBQUksR0FBRyxHQUFHLENBQUM7SUFVUixDQUFDO0lBRUosZ0JBQWdCO0lBQ2hCLEtBQUs7UUFDRCxNQUFNLEVBQUUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNwRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxLQUF5QjtRQUM1QixJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUUsQ0FBQztZQUN0QixPQUFPO1FBQ1gsQ0FBQztRQUNELElBQUksWUFBWSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUM7UUFDN0IsaUZBQWlGO1FBQ2pGLElBQUksZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLFFBQVEsQ0FBQztRQUNyQyxJQUFJLElBQUksQ0FBQyxPQUFPLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDckIsWUFBWSxHQUFHLENBQUMsQ0FBQztZQUNqQixnQkFB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OERDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBJbmNyZW1lbnRhbGx5IHVwZGF0ZWQgc3RhdGlzdGljcyBvbiBhIHNldCBvZiB2YWx1ZXMuXG4gKiBAcHVibGljXG4gKi9cbmV4cG9ydCBjbGFzcyBTdGF0aXN0aWNzIHtcbiAgICAvKiogTnVtYmVyIG9mIHZhbHVlcyBvYnNlcnZlZC4gKi9cbiAgICBzYW1wbGVzID0gMDtcbiAgICAvKiogVGhlIG1heGltdW0gdmFsdWUgb2JzZXJ2ZWQuIEluaXRpYWxpemVkIHRvIGBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFlgLiAqL1xuICAgIG1heCA9IE51bWJlci5ORUdBVElWRV9JTkZJTklUWTtcbiAgICAvKiogVGhlIG1pbmltdW0gdmFsdWUgb2JzZXJ2ZWQuIEluaXRpYWxpemVkIHRvIGBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFlgLiAqL1xuICAgIG1pbiA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWTtcbiAgICAvKiogVGhlIHZhcmlhbmNlIG9mIHRoZSB2YWx1ZXMgb2JzZXJ2ZWQuICovXG4gICAgdmFyaWFuY2UgPSAwO1xuICAgIC8qKiBUaGUgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHRoZSB2YWx1ZXMgb2JzZXJ2ZWQuICovXG4gICAgc3RkZXYgPSAwO1xuICAgIC8qKiBUaGUgbWVhbiAoYXZlcmFnZSkgb2YgdGhlIHZhbHVlcyBvYnNlcnZlZC4gKi9cbiAgICBtZWFuID0gTmFOO1xuXG4gICAgLyoqXG4gICAgICogSW5jcmVtZW50YWxseSB0cmFjayBtZWFuLCBzdGRldiwgbWluLCBtYXgsIG9mIGEgc2VxdWVuY2Ugb2YgdmFsdWVzLlxuICAgICAqIEBwYXJhbSBwcmludEZpeGVkUHJlY2lzaW9uIC0gVGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBwcmludCBpblxuICAgICAqIHtAbGluayBTdGF0aXN0aWNzLnRvU3RyaW5nfS5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgLyoqIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gcHJpbnQgaW4ge0BsaW5rIFN0YXRpc3RpY3MudG9TdHJpbmd9ICovXG4gICAgICAgIHByb3RlY3RlZCBwcmludEZpeGVkUHJlY2lzaW9uOiBudW1iZXIgPSAxXG4gICAgKSB7fVxuXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xuICAgIGNsb25lKCkge1xuICAgICAgICBjb25zdCBydiA9IG5ldyBTdGF0aXN0aWNzKHRoaXMucHJpbnRGaXhlZFByZWNpc2lvbik7XG4gICAgICAgIHJldHVybiBPYmplY3QuYXNzaWduKHJ2LCB0aGlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgc3RhdGlzdGljcyB3aXRoIGEgbmV3IHZhbHVlIGluIHRoZSBzZXF1ZW5jZS5cbiAgICAgKi9cbiAgICB1cGRhdGUodmFsdWU6IG51bWJlciB8IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGxldCBwcmV2aW91c01lYW4gPSB0aGlzLm1lYW47XG4gICAgICAgIC8vIGh0dHBzOi8vbWF0aC5zdGFja2V4Y2hhbmdlLmNvbS9xdWVzdGlvbnMvMzc0ODgxL3JlY3Vyc2l2ZS1mb3JtdWxhLWZvci12YXJpYW5jZVxuICAgICAgICBsZXQgcHJldmlvdXNWYXJpYW5jZSA9IHRoaXMudmFyaWFuY2U7XG4gICAgICAgIGlmICh0aGlzLnNhbXBsZXMgPT09IDApIHtcbiAgICAgICAgICAgIHByZXZpb3VzTWVhbiA9IDA7XG4gICAgICAgICAgICBwcmV2aW91c1ZhcmlhbmNlID0gMDtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNhbXBsZXMrKztcbiAgICAgICAgdGhpcy5tZWFuID0gcHJldmlvdXNNZWFuICsgKHZhbHVlIC0gcHJldmlvdXNNZWFuKSAvIHRoaXMuc2FtcGxlcztcbiAgICAgICAgdGhpcy52YXJpYW5jZSA9XG4gICAgICAgICAgICAoKHByZXZpb3VzVmFyaWFuY2UgKyAocHJldmlvdXNNZWFuIC0gdmFsdWUpICoqIDIgLyB0aGlzLnNhbXBsZXMpICpcbiAgICAgICAgICAgICAgICAodGhpcy5zYW1wbGVzIC0gMSkpIC9cbiAgICAgICAgICAgIHRoaXMuc2FtcGxlcztcbiAgICAgICAgdGhpcy5zdGRldiA9IE1hdGguc3FydCh0aGlzLnZhcmlhbmNlKTtcbiAgICAgICAgaWYgKHZhbHVlID4gdGhpcy5tYXgpIHtcbiAgICAgICAgICAgIHRoaXMubWF4ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHZhbHVlIDwgdGhpcy5taW4pIHtcbiAgICAgICAgICAgIHRoaXMubWluID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcmludCB0aGUgbWVhbiBvZiB0aGUgb2JzZXJ2YXRpb25zIHNlZW4sIHdpdGggdGhlIHByZWNpc2lvbiBzcGVjaWZpZWQgaW5cbiAgICAgKiB0aGUgY29uc3RydWN0b3IuXG4gICAgICovXG4gICAgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiBgJHt0aGlzLm1lYW4udG9GaXhlZCh0aGlzLnByaW50Rml4ZWRQcmVjaXNpb24pfWA7XG4gICAgfVxufVxuXG5leHBvcnQgY2xhc3MgRXhwb25lbnRpYWxseURlY2F5aW5nQXZlcmFnZVZhbHVlIHtcbiAgICBzYW1wbGVzID0gMDtcbiAgICB2YWx1ZSA9IDA7XG4gICAgY29uc3RydWN0b3IocHVibGljIHNtb290aGluZ0ZhY3RvcjogbnVtYmVyKSB7fVxuICAgIHVwZGF0ZShuOiBudW1iZXIpIHtcbiAgICAgICAgLy8gdHNsaW50OmRpc2FibGUtbmV4dC1saW5lOnByZWZlci1jb25kaXRpb25hbC1leHByZXNzaW9uXG4gICAgICAgIGlmICh0aGlzLnNhbXBsZXMrKyA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9IG47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnZhbHVlID1cbiAgICAgICAgICAgICAgICB0aGlzLnNtb290aGluZ0ZhY3RvciAqIG4gKyAoMSAtIHRoaXMuc21vb3RoaW5nRmFjdG9yKSAqIHRoaXMudmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgdG9TdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnZhbHVlO1xuICAgIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNsZWVwKG1zOiBudW1iZXIsIGNhbmNlbCA9IG5ldyBQcm9taXNlPHZvaWQ+KCgpID0+IHt9KSkge1xuICAgIGxldCBpZDogTm9kZUpTLlRpbWVyO1xuICAgIGNhbmNlbC50aGVuKF8gPT4gY2xlYXJUaW1lb3V0KGlkKSkuY2F0Y2goXyA9PiBjbGVhclRpbWVvdXQoaWQpKTtcbiAgICByZXR1cm4gUHJvbWlzZS5yYWNlKFtuZXcgUHJvbWlzZShyZXNvbHZlID0+IChpZCA9IHNldFRpbWVvdXQocmVzb2x2ZSwgbXMpKSksIGNhbmNlbF0pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc3RyZWFtVG9CdWZmZXIoczogTm9kZUpTLlJlYWRhYmxlU3RyZWFtKSB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlPEJ1ZmZlcj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICBjb25zdCBidWZmZXJzOiBCdWZmZXJbXSA9IFtdO1xuICAgICAgICBzLm9uKFwiZXJyb3JcIiwgcmVqZWN0KTtcbiAgICAgICAgcy5vbihcImRhdGFcIiwgKGRhdGE6IEJ1ZmZlcikgPT4gYnVmZmVycy5wdXNoKGRhdGEpKTtcbiAgICAgICAgcy5vbihcImVuZFwiLCAoKSA9PiByZXNvbHZlKEJ1ZmZlci5jb25jYXQoYnVmZmVycykpKTtcbiAgICB9KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNob21wKHM6IHN0cmluZykge1xuICAgIGlmIChzLmxlbmd0aCA+IDAgJiYgc1tzLmxlbmd0aCAtIDFdID09PSBcIlxcblwiKSB7XG4gICAgICAgIHMgPSBzLnNsaWNlKDAsIHMubGVuZ3RoIC0gMSk7XG4gICAgfVxuICAgIHJldHVybiBzO1xufVxuXG5leHBvcnQgY29uc3Qgc3VtID0gKGE6IG51bWJlcltdKSA9PiBhLnJlZHVjZSgodG90YWwsIG4pID0+IHRvdGFsICsgbiwgMCk7XG5cbmV4cG9ydCBmdW5jdGlvbiBvYmplY3RTaXplKG9iaj86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0pIHtcbiAgICBpZiAoIW9iaikge1xuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG4gICAgcmV0dXJuIHN1bShPYmplY3Qua2V5cyhvYmopLm1hcChrZXkgPT4ga2V5Lmxlbmd0aCArIG9ialtrZXldLmxlbmd0aCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY29tcHV0ZUh0dHBSZXNwb25zZUJ5dGVzKFxuICAgIGhlYWRlcnM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0sXG4gICAgb3B0cyA9IHsgaHR0cEhlYWRlcnM6IHRydWUsIG1pbjogMCB9XG4pIHtcbiAgICBjb25zdCBoZWFkZXJLZXlzID0gT2JqZWN0LmtleXMoaGVhZGVycyk7XG4gICAgbGV0IGNvbnRlbnRMZW5ndGggPSAwO1xuICAgIGZvciAoY29uc3Qga2V5IG9mIGhlYWRlcktleXMpIHtcbiAgICAgICAgaWYgKGtleS5tYXRjaCgvXmNvbnRlbnQtbGVuZ3RoJC9pKSkge1xuICAgICAgICAgICAgY29udGVudExlbmd0aCA9IE51bWJlcihoZWFkZXJzW2tleV0pO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKCFvcHRzLmh0dHBIZWFkZXJzKSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChjb250ZW50TGVuZ3RoLCBvcHRzLm1pbik7XG4gICAgfVxuICAgIGNvbnN0IGhlYWRlckxlbmd0aCA9IG9iamVjdFNpemUoaGVhZGVycykgKyBoZWFkZXJLZXlzLmxlbmd0aCAqIFwiOiBcIi5sZW5ndGg7XG4gICAgY29uc3Qgb3RoZXJMZW5ndGggPSAxMztcbiAgICByZXR1cm4gTWF0aC5tYXgoY29udGVudExlbmd0aCArIGhlYWRlckxlbmd0aCArIG90aGVyTGVuZ3RoLCBvcHRzLm1pbik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNFeHBpcmVkKFxuICAgIGRhdGU6IHN0cmluZyB8IG51bWJlciB8IHVuZGVmaW5lZCB8IG51bGwsXG4gICAgcmV0ZW50aW9uSW5EYXlzOiBudW1iZXJcbikge1xuICAgIGlmIChyZXRlbnRpb25JbkRheXMgPD0gMCkge1xuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgY29uc3QgdGltZXN0YW1wID0gdHlwZW9mIGRhdGUgPT09IFwic3RyaW5nXCIgPyBEYXRlLnBhcnNlKGRhdGUpIDogZGF0ZSB8fCAwO1xuICAgIHJldHVybiB0aW1lc3RhbXAgPCBEYXRlLm5vdygpIC0gcmV0ZW50aW9uSW5EYXlzICogMjQgKiA2MCAqIDYwICogMTAwMDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJvdW5kVG8xMDBtcyhuOiBudW1iZXIpIHtcbiAgICByZXR1cm4gTWF0aC5yb3VuZChuIC8gMTAwKSAqIDEwMDtcbn1cblxuZXhwb3J0IGNvbnN0IHV1aWR2NFBhdHRlcm4gPVxuICAgIFwiW2EtZjAtOV17OH0tW2EtZjAtOV17NH0tNFthLWYwLTldezN9LVs4OWFBYkJdW2EtZjAtOV17M30tW2EtZjAtOV17MTJ9XCI7XG5cbmV4cG9ydCBjb25zdCBHQiA9IDIgKiogMzA7XG5leHBvcnQgY29uc3QgTUIgPSAyICoqIDIwO1xuZXhwb3J0IGNvbnN0IEtCID0gMiAqKiAxMDtcblxuZXhwb3J0IGZ1bmN0aW9uIGYxKG46IG51bWJlcikge1xuICAgIHJldHVybiBuLnRvRml4ZWQoMSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBmMihuOiBudW1iZXIpIHtcbiAgICByZXR1cm4gbi50b0ZpeGVkKDIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24ga2V5c09mPEsgZXh0ZW5kcyBzdHJpbmcsIE8gZXh0ZW5kcyB7IFtrZXkgaW4gS106IGFueSB9PihcbiAgICBvYmo6IE9cbik6IEFycmF5PGtleW9mIE8+O1xuZXhwb3J0IGZ1bmN0aW9uIGtleXNPZjxPIGV4dGVuZHMgb2JqZWN0PihvYmo6IE8pOiBBcnJheTxrZXlvZiBPPiB7XG4gICAgcmV0dXJuIE9iamVjdC5rZXlzKG9iaikgYXMgQXJyYXk8a2V5b2YgTz47XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZWZpbmVkPFQ+KGFyZzogVCB8IHVuZGVmaW5lZCB8IG51bGwgfCB2b2lkKTogYXJnIGlzIFQge1xuICAgIHJldHVybiAhIWFyZztcbn1cblxuZXhwb3J0IGNsYXNzIE1heEhlYXAge1xuICAgIHByb3RlY3RlZCBfaGVhcDogbnVtYmVyW10gPSBbXTtcblxuICAgIGdldCBzaXplKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faGVhcC5sZW5ndGg7XG4gICAgfVxuXG4gICAgY2xlYXIoKSB7XG4gICAgICAgIHRoaXMuX2hlYXAgPSBbXTtcbiAgICB9XG5cbiAgICBwZWVrTWF4KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faGVhcFswXTtcbiAgICB9XG5cbiAgICBpbnNlcnQodmFsdWU6IG51bWJlcikge1xuICAgICAgICBjb25zdCBoID0gdGhpcy5faGVhcDtcbiAgICAgICAgaC5wdXNoKHZhbHVlKTtcbiAgICAgICAgbGV0IGkgPSBoLmxlbmd0aCAtIDE7XG4gICAgICAgIGNvbnN0IHBhcmVudE9mID0gKG46IG51bWJlcikgPT4gTWF0aC5mbG9vcigobiAtIDEpIC8gMik7XG4gICAgICAgIGxldCBwYXJlbnQgPSBwYXJlbnRPZihpKTtcbiAgICAgICAgd2hpbGUgKHBhcmVudCA+PSAwICYmIGhbaV0gPiBoW3BhcmVudF0pIHtcbiAgICAgICAgICAgIGNvbnN0IHRtcCA9IGhbcGFyZW50XTtcbiAgICAgICAgICAgIGhbcGFyZW50XSA9IGhbaV07XG4gICAgICAgICAgICBoW2ldID0gdG1wO1xuICAgICAgICAgICAgaSA9IHBhcmVudDtcbiAgICAgICAgICAgIHBhcmVudCA9IHBhcmVudE9mKGkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZXh0cmFjdE1heCgpIHtcbiAgICAgICAgY29uc3QgaCA9IHRoaXMuX2hlYXA7XG4gICAgICAgIGlmIChoLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZXh0cmFjdE1heCBjYWxsZWQgb24gZW1wdHkgaGVhcFwiKTtcbiAgICAgICAgfVxuICAgICAgICBsZXQgaSA9IDA7XG4gICAgICAgIGNvbnN0IHJ2ID0gaFswXTtcbiAgICAgICAgaFswXSA9IGhbaC5sZW5ndGggLSAxXTtcbiAgICAgICAgaC5wb3AoKTtcblxuICAgICAgICB3aGlsZSAoaSA8IGgubGVuZ3RoKSB7XG4gICAgICAgICAgICBjb25zdCBbbGVmdCwgcmlnaHRdID0gW2kgKiAyICsgMSwgaSAqIDIgKyAyXTtcbiAgICAgICAgICAgIGxldCBtYXliZTogbnVtYmVyIHwgdW5kZWZpbmVkO1xuICAgICAgICAgICAgaWYgKGhbaV0gPCBoW2xlZnRdICYmICEoaFtyaWdodF0gPiBoW2xlZnRdKSkge1xuICAgICAgICAgICAgICAgIG1heWJlID0gbGVmdDtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoaFtpXSA8IGhbcmlnaHRdKSB7XG4gICAgICAgICAgICAgICAgbWF5YmUgPSByaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtYXliZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBbaVZhbHVlLCBtVmFsdWVdID0gW2hbaV0sIGhbbWF5YmVdXTtcbiAgICAgICAgICAgIGhbaV0gPSBtVmFsdWU7XG4gICAgICAgICAgICBoW21heWJlXSA9IGlWYWx1ZTtcbiAgICAgICAgICAgIGkgPSBtYXliZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBydjtcbiAgICB9XG5cbiAgICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYXBbU3ltYm9sLml0ZXJhdG9yXSgpO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIFNtYWxsZXN0TjxUID0gdm9pZD4ge1xuICAgIHByb3RlY3RlZCBfaGVhcCA9IG5ldyBNYXhIZWFwKCk7XG4gICAgcHJvdGVjdGVkIF9tYXA6IFtudW1iZXIsIFRdW10gPSBbXTtcblxuICAgIGNvbnN0cnVjdG9yKHByb3RlY3RlZCBfc2l6ZTogbnVtYmVyKSB7fVxuXG4gICAgdXBkYXRlKGtleTogbnVtYmVyLCB2YWx1ZTogVCkge1xuICAgICAgICBpZiAodGhpcy5faGVhcC5zaXplIDwgdGhpcy5fc2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5faGVhcC5pbnNlcnQoa2V5KTtcbiAgICAgICAgICAgIHRoaXMuX21hcC5wdXNoKFtrZXksIHZhbHVlXSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGtleSA+PSB0aGlzLl9oZWFwLnBlZWtNYXgoKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX2hlYXAuaW5zZXJ0KGtleSk7XG4gICAgICAgIHRoaXMuX21hcC5wdXNoKFtrZXksIHZhbHVlXSk7XG4gICAgICAgIHRoaXMuc2hyaW5rKCk7XG4gICAgfVxuXG4gICAgcHJvdGVjdGVkIHNocmluaygpIHtcbiAgICAgICAgY29uc3QgbWF4ID0gdGhpcy5faGVhcC5leHRyYWN0TWF4KCk7XG4gICAgICAgIGxldCBpZHggPSB0aGlzLl9tYXAubGVuZ3RoO1xuICAgICAgICB3aGlsZSAoLS1pZHggPj0gMCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX21hcFtpZHhdWzBdID09PSBtYXgpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoaWR4ID09PSAtMSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBTbWFsbGVzdE46IGNvdWxkIG5vdCBmaW5kIGVudHJ5IGZvciBrZXkgJHttYXh9YCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5fbWFwLnNwbGljZShpZHgsIDEpO1xuICAgIH1cblxuICAgIFtTeW1ib2wuaXRlcmF0b3JdKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbWFwW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgICB9XG5cbiAgICBlbnRyaWVzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fbWFwW1N5bWJvbC5pdGVyYXRvcl07XG4gICAgfVxuXG4gICAga2V5cygpIHtcbiAgICAgICAgcmV0dXJuIFsuLi50aGlzLl9oZWFwXTtcbiAgICB9XG5cbiAgICBnZXQgc2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NpemU7XG4gICAgfVxuXG4gICAgY2xlYXIoKSB7XG4gICAgICAgIHRoaXMuX2hlYXAuY2xlYXIoKTtcbiAgICAgICAgdGhpcy5fbWFwID0gW107XG4gICAgfVxuXG4gICAgc2V0U2l6ZShuZXdTaXplOiBudW1iZXIpIHtcbiAgICAgICAgd2hpbGUgKHRoaXMuX3NpemUgPiBuZXdTaXplKSB7XG4gICAgICAgICAgICB0aGlzLnNocmluaygpO1xuICAgICAgICAgICAgdGhpcy5fc2l6ZS0tO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX3NpemUgPSBuZXdTaXplO1xuICAgIH1cbn1cbiJdfQ==