faastjs
Version:
Serverless batch computing made simple.
291 lines • 32.1 kB
JavaScript
"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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NoYXJlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7O0dBR0c7QUFDSCxNQUFhLFVBQVU7SUFjbkI7Ozs7T0FJRztJQUNIO0lBQ0ksMkVBQTJFO0lBQ2pFLHNCQUE4QixDQUFDO1FBQS9CLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBWTtRQXBCN0MsaUNBQWlDO1FBQ2pDLFlBQU8sR0FBRyxDQUFDLENBQUM7UUFDWiw2RUFBNkU7UUFDN0UsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQiw2RUFBNkU7UUFDN0UsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQiwyQ0FBMkM7UUFDM0MsYUFBUSxHQUFHLENBQUMsQ0FBQztRQUNiLHFEQUFxRDtRQUNyRCxVQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsaURBQWlEO1FBQ2pELFNBQUksR0FBRyxHQUFHLENBQUM7SUFVUixDQUFDO0lBRUosZ0JBQWdCO0lBQ2hCLEtBQUs7UUFDRCxNQUFNLEVBQUUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNwRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxLQUF5QjtRQUM1QixJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUU7WUFDckIsT0FBTztTQUNWO1FBQ0QsSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUM3QixpRkFBaUY7UUFDakYsSUFBSSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxDQUFDLEVBQUU7WUFDcEIsWUFBWSxHQUFHLENBQUMsQ0FBQztZQUNqQixnQkFBZ0IsR0FBRyxDQUFDLENB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ckU7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztRQUNiLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztJQUN4QyxDQUFDO0lBRUQsT0FBTztRQUNILE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELElBQUk7UUFDQSxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUVELElBQUksSUFBSTtRQUNKLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUN0QixDQUFDO0lBRUQsS0FBSztRQUNELElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU8sQ0FBQyxPQUFlO1FBQ25CLE9BQU8sSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLEVBQUU7WUFDekIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2QsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ2hCO1FBQ0QsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztDQUNKO0FBOURELDhCQThEQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogSW5jcmVtZW50YWxseSB1cGRhdGVkIHN0YXRpc3RpY3Mgb24gYSBzZXQgb2YgdmFsdWVzLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgU3RhdGlzdGljcyB7XG4gICAgLyoqIE51bWJlciBvZiB2YWx1ZXMgb2JzZXJ2ZWQuICovXG4gICAgc2FtcGxlcyA9IDA7XG4gICAgLyoqIFRoZSBtYXhpbXVtIHZhbHVlIG9ic2VydmVkLiBJbml0aWFsaXplZCB0byBgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZYC4gKi9cbiAgICBtYXggPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XG4gICAgLyoqIFRoZSBtaW5pbXVtIHZhbHVlIG9ic2VydmVkLiBJbml0aWFsaXplZCB0byBgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZYC4gKi9cbiAgICBtaW4gPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG4gICAgLyoqIFRoZSB2YXJpYW5jZSBvZiB0aGUgdmFsdWVzIG9ic2VydmVkLiAqL1xuICAgIHZhcmlhbmNlID0gMDtcbiAgICAvKiogVGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgdmFsdWVzIG9ic2VydmVkLiAqL1xuICAgIHN0ZGV2ID0gMDtcbiAgICAvKiogVGhlIG1lYW4gKGF2ZXJhZ2UpIG9mIHRoZSB2YWx1ZXMgb2JzZXJ2ZWQuICovXG4gICAgbWVhbiA9IE5hTjtcblxuICAgIC8qKlxuICAgICAqIEluY3JlbWVudGFsbHkgdHJhY2sgbWVhbiwgc3RkZXYsIG1pbiwgbWF4LCBvZiBhIHNlcXVlbmNlIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0gcHJpbnRGaXhlZFByZWNpc2lvbiAtIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gcHJpbnQgaW5cbiAgICAgKiB7QGxpbmsgU3RhdGlzdGljcy50b1N0cmluZ30uXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIC8qKiBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHByaW50IGluIHtAbGluayBTdGF0aXN0aWNzLnRvU3RyaW5nfSAqL1xuICAgICAgICBwcm90ZWN0ZWQgcHJpbnRGaXhlZFByZWNpc2lvbjogbnVtYmVyID0gMVxuICAgICkge31cblxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBjbG9uZSgpIHtcbiAgICAgICAgY29uc3QgcnYgPSBuZXcgU3RhdGlzdGljcyh0aGlzLnByaW50Rml4ZWRQcmVjaXNpb24pO1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihydiwgdGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHN0YXRpc3RpY3Mgd2l0aCBhIG5ldyB2YWx1ZSBpbiB0aGUgc2VxdWVuY2UuXG4gICAgICovXG4gICAgdXBkYXRlKHZhbHVlOiBudW1iZXIgfCB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcHJldmlvdXNNZWFuID0gdGhpcy5tZWFuO1xuICAgICAgICAvLyBodHRwczovL21hdGguc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzM3NDg4MS9yZWN1cnNpdmUtZm9ybXVsYS1mb3ItdmFyaWFuY2VcbiAgICAgICAgbGV0IHByZXZpb3VzVmFyaWFuY2UgPSB0aGlzLnZhcmlhbmNlO1xuICAgICAgICBpZiAodGhpcy5zYW1wbGVzID09PSAwKSB7XG4gICAgICAgICAgICBwcmV2aW91c01lYW4gPSAwO1xuICAgICAgICAgICAgcHJldmlvdXNWYXJpYW5jZSA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zYW1wbGVzKys7XG4gICAgICAgIHRoaXMubWVhbiA9IHByZXZpb3VzTWVhbiArICh2YWx1ZSAtIHByZXZpb3VzTWVhbikgLyB0aGlzLnNhbXBsZXM7XG4gICAgICAgIHRoaXMudmFyaWFuY2UgPVxuICAgICAgICAgICAgKChwcmV2aW91c1ZhcmlhbmNlICsgKHByZXZpb3VzTWVhbiAtIHZhbHVlKSAqKiAyIC8gdGhpcy5zYW1wbGVzKSAqXG4gICAgICAgICAgICAgICAgKHRoaXMuc2FtcGxlcyAtIDEpKSAvXG4gICAgICAgICAgICB0aGlzLnNhbXBsZXM7XG4gICAgICAgIHRoaXMuc3RkZXYgPSBNYXRoLnNxcnQodGhpcy52YXJpYW5jZSk7XG4gICAgICAgIGlmICh2YWx1ZSA+IHRoaXMubWF4KSB7XG4gICAgICAgICAgICB0aGlzLm1heCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSA8IHRoaXMubWluKSB7XG4gICAgICAgICAgICB0aGlzLm1pbiA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJpbnQgdGhlIG1lYW4gb2YgdGhlIG9ic2VydmF0aW9ucyBzZWVuLCB3aXRoIHRoZSBwcmVjaXNpb24gc3BlY2lmaWVkIGluXG4gICAgICogdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqL1xuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5tZWFuLnRvRml4ZWQodGhpcy5wcmludEZpeGVkUHJlY2lzaW9uKX1gO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEV4cG9uZW50aWFsbHlEZWNheWluZ0F2ZXJhZ2VWYWx1ZSB7XG4gICAgc2FtcGxlcyA9IDA7XG4gICAgdmFsdWUgPSAwO1xuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBzbW9vdGhpbmdGYWN0b3I6IG51bWJlcikge31cbiAgICB1cGRhdGUobjogbnVtYmVyKSB7XG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpwcmVmZXItY29uZGl0aW9uYWwtZXhwcmVzc2lvblxuICAgICAgICBpZiAodGhpcy5zYW1wbGVzKysgPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9XG4gICAgICAgICAgICAgICAgdGhpcy5zbW9vdGhpbmdGYWN0b3IgKiBuICsgKDEgLSB0aGlzLnNtb290aGluZ0ZhY3RvcikgKiB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzbGVlcChtczogbnVtYmVyLCBjYW5jZWwgPSBuZXcgUHJvbWlzZTx2b2lkPigoKSA9PiB7fSkpIHtcbiAgICBsZXQgaWQ6IE5vZGVKUy5UaW1lcjtcbiAgICBjYW5jZWwudGhlbihfID0+IGNsZWFyVGltZW91dChpZCkpLmNhdGNoKF8gPT4gY2xlYXJUaW1lb3V0KGlkKSk7XG4gICAgcmV0dXJuIFByb21pc2UucmFjZShbbmV3IFByb21pc2UocmVzb2x2ZSA9PiAoaWQgPSBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSkpLCBjYW5jZWxdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmVhbVRvQnVmZmVyKHM6IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxCdWZmZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgYnVmZmVyczogQnVmZmVyW10gPSBbXTtcbiAgICAgICAgcy5vbihcImVycm9yXCIsIHJlamVjdCk7XG4gICAgICAgIHMub24oXCJkYXRhXCIsIChkYXRhOiBCdWZmZXIpID0+IGJ1ZmZlcnMucHVzaChkYXRhKSk7XG4gICAgICAgIHMub24oXCJlbmRcIiwgKCkgPT4gcmVzb2x2ZShCdWZmZXIuY29uY2F0KGJ1ZmZlcnMpKSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjaG9tcChzOiBzdHJpbmcpIHtcbiAgICBpZiAocy5sZW5ndGggPiAwICYmIHNbcy5sZW5ndGggLSAxXSA9PT0gXCJcXG5cIikge1xuICAgICAgICBzID0gcy5zbGljZSgwLCBzLmxlbmd0aCAtIDEpO1xuICAgIH1cbiAgICByZXR1cm4gcztcbn1cblxuZXhwb3J0IGNvbnN0IHN1bSA9IChhOiBudW1iZXJbXSkgPT4gYS5yZWR1Y2UoKHRvdGFsLCBuKSA9PiB0b3RhbCArIG4sIDApO1xuXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0U2l6ZShvYmo/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KSB7XG4gICAgaWYgKCFvYmopIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIHJldHVybiBzdW0oT2JqZWN0LmtleXMob2JqKS5tYXAoa2V5ID0+IGtleS5sZW5ndGggKyBvYmpba2V5XS5sZW5ndGgpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVIdHRwUmVzcG9uc2VCeXRlcyhcbiAgICBoZWFkZXJzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9LFxuICAgIG9wdHMgPSB7IGh0dHBIZWFkZXJzOiB0cnVlLCBtaW46IDAgfVxuKSB7XG4gICAgY29uc3QgaGVhZGVyS2V5cyA9IE9iamVjdC5rZXlzKGhlYWRlcnMpO1xuICAgIGxldCBjb250ZW50TGVuZ3RoID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBoZWFkZXJLZXlzKSB7XG4gICAgICAgIGlmIChrZXkubWF0Y2goL15jb250ZW50LWxlbmd0aCQvaSkpIHtcbiAgICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSBOdW1iZXIoaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICghb3B0cy5odHRwSGVhZGVycykge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoY29udGVudExlbmd0aCwgb3B0cy5taW4pO1xuICAgIH1cbiAgICBjb25zdCBoZWFkZXJMZW5ndGggPSBvYmplY3RTaXplKGhlYWRlcnMpICsgaGVhZGVyS2V5cy5sZW5ndGggKiBcIjogXCIubGVuZ3RoO1xuICAgIGNvbnN0IG90aGVyTGVuZ3RoID0gMTM7XG4gICAgcmV0dXJuIE1hdGgubWF4KGNvbnRlbnRMZW5ndGggKyBoZWFkZXJMZW5ndGggKyBvdGhlckxlbmd0aCwgb3B0cy5taW4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzRXhwaXJlZChcbiAgICBkYXRlOiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQgfCBudWxsLFxuICAgIHJldGVudGlvbkluRGF5czogbnVtYmVyXG4pIHtcbiAgICBpZiAocmV0ZW50aW9uSW5EYXlzIDw9IDApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IHRpbWVzdGFtcCA9IHR5cGVvZiBkYXRlID09PSBcInN0cmluZ1wiID8gRGF0ZS5wYXJzZShkYXRlKSA6IGRhdGUgfHwgMDtcbiAgICByZXR1cm4gdGltZXN0YW1wIDwgRGF0ZS5ub3coKSAtIHJldGVudGlvbkluRGF5cyAqIDI0ICogNjAgKiA2MCAqIDEwMDA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByb3VuZFRvMTAwbXMobjogbnVtYmVyKSB7XG4gICAgcmV0dXJuIE1hdGgucm91bmQobiAvIDEwMCkgKiAxMDA7XG59XG5cbmV4cG9ydCBjb25zdCB1dWlkdjRQYXR0ZXJuID1cbiAgICBcIlthLWYwLTldezh9LVthLWYwLTldezR9LTRbYS1mMC05XXszfS1bODlhQWJCXVthLWYwLTldezN9LVthLWYwLTldezEyfVwiO1xuXG5leHBvcnQgY29uc3QgR0IgPSAyICoqIDMwO1xuZXhwb3J0IGNvbnN0IE1CID0gMiAqKiAyMDtcbmV4cG9ydCBjb25zdCBLQiA9IDIgKiogMTA7XG5cbmV4cG9ydCBmdW5jdGlvbiBmMShuOiBudW1iZXIpIHtcbiAgICByZXR1cm4gbi50b0ZpeGVkKDEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZjIobjogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG4udG9GaXhlZCgyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGtleXNPZjxLIGV4dGVuZHMgc3RyaW5nLCBPIGV4dGVuZHMgeyBba2V5IGluIEtdOiBhbnkgfT4oXG4gICAgb2JqOiBPXG4pOiBBcnJheTxrZXlvZiBPPjtcbmV4cG9ydCBmdW5jdGlvbiBrZXlzT2Y8TyBleHRlbmRzIG9iamVjdD4ob2JqOiBPKTogQXJyYXk8a2V5b2YgTz4ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhvYmopIGFzIEFycmF5PGtleW9mIE8+O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmaW5lZDxUPihhcmc6IFQgfCB1bmRlZmluZWQgfCBudWxsIHwgdm9pZCk6IGFyZyBpcyBUIHtcbiAgICByZXR1cm4gISFhcmc7XG59XG5cbmV4cG9ydCBjbGFzcyBNYXhIZWFwIHtcbiAgICBwcm90ZWN0ZWQgX2hlYXA6IG51bWJlcltdID0gW107XG5cbiAgICBnZXQgc2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYXAubGVuZ3RoO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLl9oZWFwID0gW107XG4gICAgfVxuXG4gICAgcGVla01heCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYXBbMF07XG4gICAgfVxuXG4gICAgaW5zZXJ0KHZhbHVlOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3QgaCA9IHRoaXMuX2hlYXA7XG4gICAgICAgIGgucHVzaCh2YWx1ZSk7XG4gICAgICAgIGxldCBpID0gaC5sZW5ndGggLSAxO1xuICAgICAgICBjb25zdCBwYXJlbnRPZiA9IChuOiBudW1iZXIpID0+IE1hdGguZmxvb3IoKG4gLSAxKSAvIDIpO1xuICAgICAgICBsZXQgcGFyZW50ID0gcGFyZW50T2YoaSk7XG4gICAgICAgIHdoaWxlIChwYXJlbnQgPj0gMCAmJiBoW2ldID4gaFtwYXJlbnRdKSB7XG4gICAgICAgICAgICBjb25zdCB0bXAgPSBoW3BhcmVudF07XG4gICAgICAgICAgICBoW3BhcmVudF0gPSBoW2ldO1xuICAgICAgICAgICAgaFtpXSA9IHRtcDtcbiAgICAgICAgICAgIGkgPSBwYXJlbnQ7XG4gICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnRPZihpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGV4dHJhY3RNYXgoKSB7XG4gICAgICAgIGNvbnN0IGggPSB0aGlzLl9oZWFwO1xuICAgICAgICBpZiAoaC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImV4dHJhY3RNYXggY2FsbGVkIG9uIGVtcHR5IGhlYXBcIik7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICBjb25zdCBydiA9IGhbMF07XG4gICAgICAgIGhbMF0gPSBoW2gubGVuZ3RoIC0gMV07XG4gICAgICAgIGgucG9wKCk7XG5cbiAgICAgICAgd2hpbGUgKGkgPCBoLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgW2xlZnQsIHJpZ2h0XSA9IFtpICogMiArIDEsIGkgKiAyICsgMl07XG4gICAgICAgICAgICBsZXQgbWF5YmU6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChoW2ldIDwgaFtsZWZ0XSAmJiAhKGhbcmlnaHRdID4gaFtsZWZ0XSkpIHtcbiAgICAgICAgICAgICAgICBtYXliZSA9IGxlZnQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhbaV0gPCBoW3JpZ2h0XSkge1xuICAgICAgICAgICAgICAgIG1heWJlID0gcmlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWF5YmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgW2lWYWx1ZSwgbVZhbHVlXSA9IFtoW2ldLCBoW21heWJlXV07XG4gICAgICAgICAgICBoW2ldID0gbVZhbHVlO1xuICAgICAgICAgICAgaFttYXliZV0gPSBpVmFsdWU7XG4gICAgICAgICAgICBpID0gbWF5YmU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcnY7XG4gICAgfVxuXG4gICAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oZWFwW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTbWFsbGVzdE48VCA9IHZvaWQ+IHtcbiAgICBwcm90ZWN0ZWQgX2hlYXAgPSBuZXcgTWF4SGVhcCgpO1xuICAgIHByb3RlY3RlZCBfbWFwOiBbbnVtYmVyLCBUXVtdID0gW107XG5cbiAgICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgX3NpemU6IG51bWJlcikge31cblxuICAgIHVwZGF0ZShrZXk6IG51bWJlciwgdmFsdWU6IFQpIHtcbiAgICAgICAgaWYgKHRoaXMuX2hlYXAuc2l6ZSA8IHRoaXMuX3NpemUpIHtcbiAgICAgICAgICAgIHRoaXMuX2hlYXAuaW5zZXJ0KGtleSk7XG4gICAgICAgICAgICB0aGlzLl9tYXAucHVzaChba2V5LCB2YWx1ZV0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXkgPj0gdGhpcy5faGVhcC5wZWVrTWF4KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9oZWFwLmluc2VydChrZXkpO1xuICAgICAgICB0aGlzLl9tYXAucHVzaChba2V5LCB2YWx1ZV0pO1xuICAgICAgICB0aGlzLnNocmluaygpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzaHJpbmsoKSB7XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMuX2hlYXAuZXh0cmFjdE1heCgpO1xuICAgICAgICBsZXQgaWR4ID0gdGhpcy5fbWFwLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKC0taWR4ID49IDApIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9tYXBbaWR4XVswXSA9PT0gbWF4KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU21hbGxlc3ROOiBjb3VsZCBub3QgZmluZCBlbnRyeSBmb3Iga2V5ICR7bWF4fWApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX21hcC5zcGxpY2UoaWR4LCAxKTtcbiAgICB9XG5cbiAgICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21hcFtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gICAgfVxuXG4gICAgZW50cmllcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21hcFtTeW1ib2wuaXRlcmF0b3JdO1xuICAgIH1cblxuICAgIGtleXMoKSB7XG4gICAgICAgIHJldHVybiBbLi4udGhpcy5faGVhcF07XG4gICAgfVxuXG4gICAgZ2V0IHNpemUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zaXplO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLl9oZWFwLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuX21hcCA9IFtdO1xuICAgIH1cblxuICAgIHNldFNpemUobmV3U2l6ZTogbnVtYmVyKSB7XG4gICAgICAgIHdoaWxlICh0aGlzLl9zaXplID4gbmV3U2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5zaHJpbmsoKTtcbiAgICAgICAgICAgIHRoaXMuX3NpemUtLTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zaXplID0gbmV3U2l6ZTtcbiAgICB9XG59XG4iXX0=