UNPKG

32.1 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.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;
4/**
5 * Incrementally updated statistics on a set of values.
6 * @public
7 */
8class Statistics {
9 /**
10 * Incrementally track mean, stdev, min, max, of a sequence of values.
11 * @param printFixedPrecision - The number of decimal places to print in
12 * {@link Statistics.toString}.
13 */
14 constructor(
15 /** The number of decimal places to print in {@link Statistics.toString} */
16 printFixedPrecision = 1) {
17 this.printFixedPrecision = printFixedPrecision;
18 /** Number of values observed. */
19 this.samples = 0;
20 /** The maximum value observed. Initialized to `Number.NEGATIVE_INFINITY`. */
21 this.max = Number.NEGATIVE_INFINITY;
22 /** The minimum value observed. Initialized to `Number.POSITIVE_INFINITY`. */
23 this.min = Number.POSITIVE_INFINITY;
24 /** The variance of the values observed. */
25 this.variance = 0;
26 /** The standard deviation of the values observed. */
27 this.stdev = 0;
28 /** The mean (average) of the values observed. */
29 this.mean = NaN;
30 }
31 /** @internal */
32 clone() {
33 const rv = new Statistics(this.printFixedPrecision);
34 return Object.assign(rv, this);
35 }
36 /**
37 * Update statistics with a new value in the sequence.
38 */
39 update(value) {
40 if (value === undefined) {
41 return;
42 }
43 let previousMean = this.mean;
44 // https://math.stackexchange.com/questions/374881/recursive-formula-for-variance
45 let previousVariance = this.variance;
46 if (this.samples === 0) {
47 previousMean = 0;
48 previousVariance = 0;
49 }
50 this.samples++;
51 this.mean = previousMean + (value - previousMean) / this.samples;
52 this.variance =
53 ((previousVariance + (previousMean - value) ** 2 / this.samples) *
54 (this.samples - 1)) /
55 this.samples;
56 this.stdev = Math.sqrt(this.variance);
57 if (value > this.max) {
58 this.max = value;
59 }
60 if (value < this.min) {
61 this.min = value;
62 }
63 }
64 /**
65 * Print the mean of the observations seen, with the precision specified in
66 * the constructor.
67 */
68 toString() {
69 return `${this.mean.toFixed(this.printFixedPrecision)}`;
70 }
71}
72exports.Statistics = Statistics;
73class ExponentiallyDecayingAverageValue {
74 constructor(smoothingFactor) {
75 this.smoothingFactor = smoothingFactor;
76 this.samples = 0;
77 this.value = 0;
78 }
79 update(n) {
80 // tslint:disable-next-line:prefer-conditional-expression
81 if (this.samples++ === 0) {
82 this.value = n;
83 }
84 else {
85 this.value =
86 this.smoothingFactor * n + (1 - this.smoothingFactor) * this.value;
87 }
88 }
89 toString() {
90 return this.value;
91 }
92}
93exports.ExponentiallyDecayingAverageValue = ExponentiallyDecayingAverageValue;
94function sleep(ms, cancel = new Promise(() => { })) {
95 let id;
96 cancel.then(_ => clearTimeout(id)).catch(_ => clearTimeout(id));
97 return Promise.race([new Promise(resolve => (id = setTimeout(resolve, ms))), cancel]);
98}
99exports.sleep = sleep;
100function streamToBuffer(s) {
101 return new Promise((resolve, reject) => {
102 const buffers = [];
103 s.on("error", reject);
104 s.on("data", (data) => buffers.push(data));
105 s.on("end", () => resolve(Buffer.concat(buffers)));
106 });
107}
108exports.streamToBuffer = streamToBuffer;
109function chomp(s) {
110 if (s.length > 0 && s[s.length - 1] === "\n") {
111 s = s.slice(0, s.length - 1);
112 }
113 return s;
114}
115exports.chomp = chomp;
116const sum = (a) => a.reduce((total, n) => total + n, 0);
117exports.sum = sum;
118function objectSize(obj) {
119 if (!obj) {
120 return 0;
121 }
122 return (0, exports.sum)(Object.keys(obj).map(key => key.length + obj[key].length));
123}
124exports.objectSize = objectSize;
125function computeHttpResponseBytes(headers, opts = { httpHeaders: true, min: 0 }) {
126 const headerKeys = Object.keys(headers);
127 let contentLength = 0;
128 for (const key of headerKeys) {
129 if (key.match(/^content-length$/i)) {
130 contentLength = Number(headers[key]);
131 break;
132 }
133 }
134 if (!opts.httpHeaders) {
135 return Math.max(contentLength, opts.min);
136 }
137 const headerLength = objectSize(headers) + headerKeys.length * ": ".length;
138 const otherLength = 13;
139 return Math.max(contentLength + headerLength + otherLength, opts.min);
140}
141exports.computeHttpResponseBytes = computeHttpResponseBytes;
142function hasExpired(date, retentionInDays) {
143 if (retentionInDays <= 0) {
144 return true;
145 }
146 const timestamp = typeof date === "string" ? Date.parse(date) : date || 0;
147 return timestamp < Date.now() - retentionInDays * 24 * 60 * 60 * 1000;
148}
149exports.hasExpired = hasExpired;
150function roundTo100ms(n) {
151 return Math.round(n / 100) * 100;
152}
153exports.roundTo100ms = roundTo100ms;
154exports.uuidv4Pattern = "[a-f0-9]{8}-[a-f0-9]{4}-4[a-f0-9]{3}-[89aAbB][a-f0-9]{3}-[a-f0-9]{12}";
155exports.GB = 2 ** 30;
156exports.MB = 2 ** 20;
157exports.KB = 2 ** 10;
158function f1(n) {
159 return n.toFixed(1);
160}
161exports.f1 = f1;
162function f2(n) {
163 return n.toFixed(2);
164}
165exports.f2 = f2;
166function keysOf(obj) {
167 return Object.keys(obj);
168}
169exports.keysOf = keysOf;
170function defined(arg) {
171 return !!arg;
172}
173exports.defined = defined;
174class MaxHeap {
175 constructor() {
176 this._heap = [];
177 }
178 get size() {
179 return this._heap.length;
180 }
181 clear() {
182 this._heap = [];
183 }
184 peekMax() {
185 return this._heap[0];
186 }
187 insert(value) {
188 const h = this._heap;
189 h.push(value);
190 let i = h.length - 1;
191 const parentOf = (n) => Math.floor((n - 1) / 2);
192 let parent = parentOf(i);
193 while (parent >= 0 && h[i] > h[parent]) {
194 const tmp = h[parent];
195 h[parent] = h[i];
196 h[i] = tmp;
197 i = parent;
198 parent = parentOf(i);
199 }
200 }
201 extractMax() {
202 const h = this._heap;
203 if (h.length === 0) {
204 throw new Error("extractMax called on empty heap");
205 }
206 let i = 0;
207 const rv = h[0];
208 h[0] = h[h.length - 1];
209 h.pop();
210 while (i < h.length) {
211 const [left, right] = [i * 2 + 1, i * 2 + 2];
212 let maybe;
213 if (h[i] < h[left] && !(h[right] > h[left])) {
214 maybe = left;
215 }
216 else if (h[i] < h[right]) {
217 maybe = right;
218 }
219 if (maybe === undefined) {
220 break;
221 }
222 const [iValue, mValue] = [h[i], h[maybe]];
223 h[i] = mValue;
224 h[maybe] = iValue;
225 i = maybe;
226 }
227 return rv;
228 }
229 [Symbol.iterator]() {
230 return this._heap[Symbol.iterator]();
231 }
232}
233exports.MaxHeap = MaxHeap;
234class SmallestN {
235 constructor(_size) {
236 this._size = _size;
237 this._heap = new MaxHeap();
238 this._map = [];
239 }
240 update(key, value) {
241 if (this._heap.size < this._size) {
242 this._heap.insert(key);
243 this._map.push([key, value]);
244 return;
245 }
246 if (key >= this._heap.peekMax()) {
247 return;
248 }
249 this._heap.insert(key);
250 this._map.push([key, value]);
251 this.shrink();
252 }
253 shrink() {
254 const max = this._heap.extractMax();
255 let idx = this._map.length;
256 while (--idx >= 0) {
257 if (this._map[idx][0] === max) {
258 break;
259 }
260 }
261 if (idx === -1) {
262 throw new Error(`SmallestN: could not find entry for key ${max}`);
263 }
264 this._map.splice(idx, 1);
265 }
266 [Symbol.iterator]() {
267 return this._map[Symbol.iterator]();
268 }
269 entries() {
270 return this._map[Symbol.iterator];
271 }
272 keys() {
273 return [...this._heap];
274 }
275 get size() {
276 return this._size;
277 }
278 clear() {
279 this._heap.clear();
280 this._map = [];
281 }
282 setSize(newSize) {
283 while (this._size > newSize) {
284 this.shrink();
285 this._size--;
286 }
287 this._size = newSize;
288 }
289}
290exports.SmallestN = SmallestN;
291//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2hhcmVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3NoYXJlZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQTs7O0dBR0c7QUFDSCxNQUFhLFVBQVU7SUFjbkI7Ozs7T0FJRztJQUNIO0lBQ0ksMkVBQTJFO0lBQ2pFLHNCQUE4QixDQUFDO1FBQS9CLHdCQUFtQixHQUFuQixtQkFBbUIsQ0FBWTtRQXBCN0MsaUNBQWlDO1FBQ2pDLFlBQU8sR0FBRyxDQUFDLENBQUM7UUFDWiw2RUFBNkU7UUFDN0UsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQiw2RUFBNkU7UUFDN0UsUUFBRyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQztRQUMvQiwyQ0FBMkM7UUFDM0MsYUFBUSxHQUFHLENBQUMsQ0FBQztRQUNiLHFEQUFxRDtRQUNyRCxVQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ1YsaURBQWlEO1FBQ2pELFNBQUksR0FBRyxHQUFHLENBQUM7SUFVUixDQUFDO0lBRUosZ0JBQWdCO0lBQ2hCLEtBQUs7UUFDRCxNQUFNLEVBQUUsR0FBRyxJQUFJLFVBQVUsQ0FBQyxJQUFJLENBQUMsbUJBQW1CLENBQUMsQ0FBQztRQUNwRCxPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ25DLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxLQUF5QjtRQUM1QixJQUFJLEtBQUssS0FBSyxTQUFTLEVBQUU7WUFDckIsT0FBTztTQUNWO1FBQ0QsSUFBSSxZQUFZLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztRQUM3QixpRkFBaUY7UUFDakYsSUFBSSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1FBQ3JDLElBQUksSUFBSSxDQUFDLE9BQU8sS0FBSyxDQUFDLEVBQUU7WUFDcEIsWUFBWSxHQUFHLENBQUMsQ0FBQztZQUNqQixnQkFBZ0IsR0FBRyxDQUFDLENB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ckU7UUFDRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVELENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQztRQUNiLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztJQUN4QyxDQUFDO0lBRUQsT0FBTztRQUNILE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDdEMsQ0FBQztJQUVELElBQUk7UUFDQSxPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0IsQ0FBQztJQUVELElBQUksSUFBSTtRQUNKLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQztJQUN0QixDQUFDO0lBRUQsS0FBSztRQUNELElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbkIsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7SUFDbkIsQ0FBQztJQUVELE9BQU8sQ0FBQyxPQUFlO1FBQ25CLE9BQU8sSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLEVBQUU7WUFDekIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQ2QsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDO1NBQ2hCO1FBQ0QsSUFBSSxDQUFDLEtBQUssR0FBRyxPQUFPLENBQUM7SUFDekIsQ0FBQztDQUNKO0FBOURELDhCQThEQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogSW5jcmVtZW50YWxseSB1cGRhdGVkIHN0YXRpc3RpY3Mgb24gYSBzZXQgb2YgdmFsdWVzLlxuICogQHB1YmxpY1xuICovXG5leHBvcnQgY2xhc3MgU3RhdGlzdGljcyB7XG4gICAgLyoqIE51bWJlciBvZiB2YWx1ZXMgb2JzZXJ2ZWQuICovXG4gICAgc2FtcGxlcyA9IDA7XG4gICAgLyoqIFRoZSBtYXhpbXVtIHZhbHVlIG9ic2VydmVkLiBJbml0aWFsaXplZCB0byBgTnVtYmVyLk5FR0FUSVZFX0lORklOSVRZYC4gKi9cbiAgICBtYXggPSBOdW1iZXIuTkVHQVRJVkVfSU5GSU5JVFk7XG4gICAgLyoqIFRoZSBtaW5pbXVtIHZhbHVlIG9ic2VydmVkLiBJbml0aWFsaXplZCB0byBgTnVtYmVyLlBPU0lUSVZFX0lORklOSVRZYC4gKi9cbiAgICBtaW4gPSBOdW1iZXIuUE9TSVRJVkVfSU5GSU5JVFk7XG4gICAgLyoqIFRoZSB2YXJpYW5jZSBvZiB0aGUgdmFsdWVzIG9ic2VydmVkLiAqL1xuICAgIHZhcmlhbmNlID0gMDtcbiAgICAvKiogVGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgdmFsdWVzIG9ic2VydmVkLiAqL1xuICAgIHN0ZGV2ID0gMDtcbiAgICAvKiogVGhlIG1lYW4gKGF2ZXJhZ2UpIG9mIHRoZSB2YWx1ZXMgb2JzZXJ2ZWQuICovXG4gICAgbWVhbiA9IE5hTjtcblxuICAgIC8qKlxuICAgICAqIEluY3JlbWVudGFsbHkgdHJhY2sgbWVhbiwgc3RkZXYsIG1pbiwgbWF4LCBvZiBhIHNlcXVlbmNlIG9mIHZhbHVlcy5cbiAgICAgKiBAcGFyYW0gcHJpbnRGaXhlZFByZWNpc2lvbiAtIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gcHJpbnQgaW5cbiAgICAgKiB7QGxpbmsgU3RhdGlzdGljcy50b1N0cmluZ30uXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoXG4gICAgICAgIC8qKiBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHByaW50IGluIHtAbGluayBTdGF0aXN0aWNzLnRvU3RyaW5nfSAqL1xuICAgICAgICBwcm90ZWN0ZWQgcHJpbnRGaXhlZFByZWNpc2lvbjogbnVtYmVyID0gMVxuICAgICkge31cblxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBjbG9uZSgpIHtcbiAgICAgICAgY29uc3QgcnYgPSBuZXcgU3RhdGlzdGljcyh0aGlzLnByaW50Rml4ZWRQcmVjaXNpb24pO1xuICAgICAgICByZXR1cm4gT2JqZWN0LmFzc2lnbihydiwgdGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHN0YXRpc3RpY3Mgd2l0aCBhIG5ldyB2YWx1ZSBpbiB0aGUgc2VxdWVuY2UuXG4gICAgICovXG4gICAgdXBkYXRlKHZhbHVlOiBudW1iZXIgfCB1bmRlZmluZWQpIHtcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBsZXQgcHJldmlvdXNNZWFuID0gdGhpcy5tZWFuO1xuICAgICAgICAvLyBodHRwczovL21hdGguc3RhY2tleGNoYW5nZS5jb20vcXVlc3Rpb25zLzM3NDg4MS9yZWN1cnNpdmUtZm9ybXVsYS1mb3ItdmFyaWFuY2VcbiAgICAgICAgbGV0IHByZXZpb3VzVmFyaWFuY2UgPSB0aGlzLnZhcmlhbmNlO1xuICAgICAgICBpZiAodGhpcy5zYW1wbGVzID09PSAwKSB7XG4gICAgICAgICAgICBwcmV2aW91c01lYW4gPSAwO1xuICAgICAgICAgICAgcHJldmlvdXNWYXJpYW5jZSA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zYW1wbGVzKys7XG4gICAgICAgIHRoaXMubWVhbiA9IHByZXZpb3VzTWVhbiArICh2YWx1ZSAtIHByZXZpb3VzTWVhbikgLyB0aGlzLnNhbXBsZXM7XG4gICAgICAgIHRoaXMudmFyaWFuY2UgPVxuICAgICAgICAgICAgKChwcmV2aW91c1ZhcmlhbmNlICsgKHByZXZpb3VzTWVhbiAtIHZhbHVlKSAqKiAyIC8gdGhpcy5zYW1wbGVzKSAqXG4gICAgICAgICAgICAgICAgKHRoaXMuc2FtcGxlcyAtIDEpKSAvXG4gICAgICAgICAgICB0aGlzLnNhbXBsZXM7XG4gICAgICAgIHRoaXMuc3RkZXYgPSBNYXRoLnNxcnQodGhpcy52YXJpYW5jZSk7XG4gICAgICAgIGlmICh2YWx1ZSA+IHRoaXMubWF4KSB7XG4gICAgICAgICAgICB0aGlzLm1heCA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2YWx1ZSA8IHRoaXMubWluKSB7XG4gICAgICAgICAgICB0aGlzLm1pbiA9IHZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJpbnQgdGhlIG1lYW4gb2YgdGhlIG9ic2VydmF0aW9ucyBzZWVuLCB3aXRoIHRoZSBwcmVjaXNpb24gc3BlY2lmaWVkIGluXG4gICAgICogdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqL1xuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gYCR7dGhpcy5tZWFuLnRvRml4ZWQodGhpcy5wcmludEZpeGVkUHJlY2lzaW9uKX1gO1xuICAgIH1cbn1cblxuZXhwb3J0IGNsYXNzIEV4cG9uZW50aWFsbHlEZWNheWluZ0F2ZXJhZ2VWYWx1ZSB7XG4gICAgc2FtcGxlcyA9IDA7XG4gICAgdmFsdWUgPSAwO1xuICAgIGNvbnN0cnVjdG9yKHB1YmxpYyBzbW9vdGhpbmdGYWN0b3I6IG51bWJlcikge31cbiAgICB1cGRhdGUobjogbnVtYmVyKSB7XG4gICAgICAgIC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZTpwcmVmZXItY29uZGl0aW9uYWwtZXhwcmVzc2lvblxuICAgICAgICBpZiAodGhpcy5zYW1wbGVzKysgPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMudmFsdWUgPSBuO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52YWx1ZSA9XG4gICAgICAgICAgICAgICAgdGhpcy5zbW9vdGhpbmdGYWN0b3IgKiBuICsgKDEgLSB0aGlzLnNtb290aGluZ0ZhY3RvcikgKiB0aGlzLnZhbHVlO1xuICAgICAgICB9XG4gICAgfVxuICAgIHRvU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gdGhpcy52YWx1ZTtcbiAgICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzbGVlcChtczogbnVtYmVyLCBjYW5jZWwgPSBuZXcgUHJvbWlzZTx2b2lkPigoKSA9PiB7fSkpIHtcbiAgICBsZXQgaWQ6IE5vZGVKUy5UaW1lcjtcbiAgICBjYW5jZWwudGhlbihfID0+IGNsZWFyVGltZW91dChpZCkpLmNhdGNoKF8gPT4gY2xlYXJUaW1lb3V0KGlkKSk7XG4gICAgcmV0dXJuIFByb21pc2UucmFjZShbbmV3IFByb21pc2UocmVzb2x2ZSA9PiAoaWQgPSBzZXRUaW1lb3V0KHJlc29sdmUsIG1zKSkpLCBjYW5jZWxdKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHN0cmVhbVRvQnVmZmVyKHM6IE5vZGVKUy5SZWFkYWJsZVN0cmVhbSkge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZTxCdWZmZXI+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgY29uc3QgYnVmZmVyczogQnVmZmVyW10gPSBbXTtcbiAgICAgICAgcy5vbihcImVycm9yXCIsIHJlamVjdCk7XG4gICAgICAgIHMub24oXCJkYXRhXCIsIChkYXRhOiBCdWZmZXIpID0+IGJ1ZmZlcnMucHVzaChkYXRhKSk7XG4gICAgICAgIHMub24oXCJlbmRcIiwgKCkgPT4gcmVzb2x2ZShCdWZmZXIuY29uY2F0KGJ1ZmZlcnMpKSk7XG4gICAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjaG9tcChzOiBzdHJpbmcpIHtcbiAgICBpZiAocy5sZW5ndGggPiAwICYmIHNbcy5sZW5ndGggLSAxXSA9PT0gXCJcXG5cIikge1xuICAgICAgICBzID0gcy5zbGljZSgwLCBzLmxlbmd0aCAtIDEpO1xuICAgIH1cbiAgICByZXR1cm4gcztcbn1cblxuZXhwb3J0IGNvbnN0IHN1bSA9IChhOiBudW1iZXJbXSkgPT4gYS5yZWR1Y2UoKHRvdGFsLCBuKSA9PiB0b3RhbCArIG4sIDApO1xuXG5leHBvcnQgZnVuY3Rpb24gb2JqZWN0U2l6ZShvYmo/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9KSB7XG4gICAgaWYgKCFvYmopIHtcbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIHJldHVybiBzdW0oT2JqZWN0LmtleXMob2JqKS5tYXAoa2V5ID0+IGtleS5sZW5ndGggKyBvYmpba2V5XS5sZW5ndGgpKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNvbXB1dGVIdHRwUmVzcG9uc2VCeXRlcyhcbiAgICBoZWFkZXJzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9LFxuICAgIG9wdHMgPSB7IGh0dHBIZWFkZXJzOiB0cnVlLCBtaW46IDAgfVxuKSB7XG4gICAgY29uc3QgaGVhZGVyS2V5cyA9IE9iamVjdC5rZXlzKGhlYWRlcnMpO1xuICAgIGxldCBjb250ZW50TGVuZ3RoID0gMDtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBoZWFkZXJLZXlzKSB7XG4gICAgICAgIGlmIChrZXkubWF0Y2goL15jb250ZW50LWxlbmd0aCQvaSkpIHtcbiAgICAgICAgICAgIGNvbnRlbnRMZW5ndGggPSBOdW1iZXIoaGVhZGVyc1trZXldKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgfVxuICAgIGlmICghb3B0cy5odHRwSGVhZGVycykge1xuICAgICAgICByZXR1cm4gTWF0aC5tYXgoY29udGVudExlbmd0aCwgb3B0cy5taW4pO1xuICAgIH1cbiAgICBjb25zdCBoZWFkZXJMZW5ndGggPSBvYmplY3RTaXplKGhlYWRlcnMpICsgaGVhZGVyS2V5cy5sZW5ndGggKiBcIjogXCIubGVuZ3RoO1xuICAgIGNvbnN0IG90aGVyTGVuZ3RoID0gMTM7XG4gICAgcmV0dXJuIE1hdGgubWF4KGNvbnRlbnRMZW5ndGggKyBoZWFkZXJMZW5ndGggKyBvdGhlckxlbmd0aCwgb3B0cy5taW4pO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaGFzRXhwaXJlZChcbiAgICBkYXRlOiBzdHJpbmcgfCBudW1iZXIgfCB1bmRlZmluZWQgfCBudWxsLFxuICAgIHJldGVudGlvbkluRGF5czogbnVtYmVyXG4pIHtcbiAgICBpZiAocmV0ZW50aW9uSW5EYXlzIDw9IDApIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGNvbnN0IHRpbWVzdGFtcCA9IHR5cGVvZiBkYXRlID09PSBcInN0cmluZ1wiID8gRGF0ZS5wYXJzZShkYXRlKSA6IGRhdGUgfHwgMDtcbiAgICByZXR1cm4gdGltZXN0YW1wIDwgRGF0ZS5ub3coKSAtIHJldGVudGlvbkluRGF5cyAqIDI0ICogNjAgKiA2MCAqIDEwMDA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByb3VuZFRvMTAwbXMobjogbnVtYmVyKSB7XG4gICAgcmV0dXJuIE1hdGgucm91bmQobiAvIDEwMCkgKiAxMDA7XG59XG5cbmV4cG9ydCBjb25zdCB1dWlkdjRQYXR0ZXJuID1cbiAgICBcIlthLWYwLTldezh9LVthLWYwLTldezR9LTRbYS1mMC05XXszfS1bODlhQWJCXVthLWYwLTldezN9LVthLWYwLTldezEyfVwiO1xuXG5leHBvcnQgY29uc3QgR0IgPSAyICoqIDMwO1xuZXhwb3J0IGNvbnN0IE1CID0gMiAqKiAyMDtcbmV4cG9ydCBjb25zdCBLQiA9IDIgKiogMTA7XG5cbmV4cG9ydCBmdW5jdGlvbiBmMShuOiBudW1iZXIpIHtcbiAgICByZXR1cm4gbi50b0ZpeGVkKDEpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZjIobjogbnVtYmVyKSB7XG4gICAgcmV0dXJuIG4udG9GaXhlZCgyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGtleXNPZjxLIGV4dGVuZHMgc3RyaW5nLCBPIGV4dGVuZHMgeyBba2V5IGluIEtdOiBhbnkgfT4oXG4gICAgb2JqOiBPXG4pOiBBcnJheTxrZXlvZiBPPjtcbmV4cG9ydCBmdW5jdGlvbiBrZXlzT2Y8TyBleHRlbmRzIG9iamVjdD4ob2JqOiBPKTogQXJyYXk8a2V5b2YgTz4ge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhvYmopIGFzIEFycmF5PGtleW9mIE8+O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVmaW5lZDxUPihhcmc6IFQgfCB1bmRlZmluZWQgfCBudWxsIHwgdm9pZCk6IGFyZyBpcyBUIHtcbiAgICByZXR1cm4gISFhcmc7XG59XG5cbmV4cG9ydCBjbGFzcyBNYXhIZWFwIHtcbiAgICBwcm90ZWN0ZWQgX2hlYXA6IG51bWJlcltdID0gW107XG5cbiAgICBnZXQgc2l6ZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYXAubGVuZ3RoO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLl9oZWFwID0gW107XG4gICAgfVxuXG4gICAgcGVla01heCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlYXBbMF07XG4gICAgfVxuXG4gICAgaW5zZXJ0KHZhbHVlOiBudW1iZXIpIHtcbiAgICAgICAgY29uc3QgaCA9IHRoaXMuX2hlYXA7XG4gICAgICAgIGgucHVzaCh2YWx1ZSk7XG4gICAgICAgIGxldCBpID0gaC5sZW5ndGggLSAxO1xuICAgICAgICBjb25zdCBwYXJlbnRPZiA9IChuOiBudW1iZXIpID0+IE1hdGguZmxvb3IoKG4gLSAxKSAvIDIpO1xuICAgICAgICBsZXQgcGFyZW50ID0gcGFyZW50T2YoaSk7XG4gICAgICAgIHdoaWxlIChwYXJlbnQgPj0gMCAmJiBoW2ldID4gaFtwYXJlbnRdKSB7XG4gICAgICAgICAgICBjb25zdCB0bXAgPSBoW3BhcmVudF07XG4gICAgICAgICAgICBoW3BhcmVudF0gPSBoW2ldO1xuICAgICAgICAgICAgaFtpXSA9IHRtcDtcbiAgICAgICAgICAgIGkgPSBwYXJlbnQ7XG4gICAgICAgICAgICBwYXJlbnQgPSBwYXJlbnRPZihpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGV4dHJhY3RNYXgoKSB7XG4gICAgICAgIGNvbnN0IGggPSB0aGlzLl9oZWFwO1xuICAgICAgICBpZiAoaC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcImV4dHJhY3RNYXggY2FsbGVkIG9uIGVtcHR5IGhlYXBcIik7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICBjb25zdCBydiA9IGhbMF07XG4gICAgICAgIGhbMF0gPSBoW2gubGVuZ3RoIC0gMV07XG4gICAgICAgIGgucG9wKCk7XG5cbiAgICAgICAgd2hpbGUgKGkgPCBoLmxlbmd0aCkge1xuICAgICAgICAgICAgY29uc3QgW2xlZnQsIHJpZ2h0XSA9IFtpICogMiArIDEsIGkgKiAyICsgMl07XG4gICAgICAgICAgICBsZXQgbWF5YmU6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgICAgICAgIGlmIChoW2ldIDwgaFtsZWZ0XSAmJiAhKGhbcmlnaHRdID4gaFtsZWZ0XSkpIHtcbiAgICAgICAgICAgICAgICBtYXliZSA9IGxlZnQ7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGhbaV0gPCBoW3JpZ2h0XSkge1xuICAgICAgICAgICAgICAgIG1heWJlID0gcmlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAobWF5YmUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgW2lWYWx1ZSwgbVZhbHVlXSA9IFtoW2ldLCBoW21heWJlXV07XG4gICAgICAgICAgICBoW2ldID0gbVZhbHVlO1xuICAgICAgICAgICAgaFttYXliZV0gPSBpVmFsdWU7XG4gICAgICAgICAgICBpID0gbWF5YmU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcnY7XG4gICAgfVxuXG4gICAgW1N5bWJvbC5pdGVyYXRvcl0oKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9oZWFwW1N5bWJvbC5pdGVyYXRvcl0oKTtcbiAgICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTbWFsbGVzdE48VCA9IHZvaWQ+IHtcbiAgICBwcm90ZWN0ZWQgX2hlYXAgPSBuZXcgTWF4SGVhcCgpO1xuICAgIHByb3RlY3RlZCBfbWFwOiBbbnVtYmVyLCBUXVtdID0gW107XG5cbiAgICBjb25zdHJ1Y3Rvcihwcm90ZWN0ZWQgX3NpemU6IG51bWJlcikge31cblxuICAgIHVwZGF0ZShrZXk6IG51bWJlciwgdmFsdWU6IFQpIHtcbiAgICAgICAgaWYgKHRoaXMuX2hlYXAuc2l6ZSA8IHRoaXMuX3NpemUpIHtcbiAgICAgICAgICAgIHRoaXMuX2hlYXAuaW5zZXJ0KGtleSk7XG4gICAgICAgICAgICB0aGlzLl9tYXAucHVzaChba2V5LCB2YWx1ZV0pO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXkgPj0gdGhpcy5faGVhcC5wZWVrTWF4KCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9oZWFwLmluc2VydChrZXkpO1xuICAgICAgICB0aGlzLl9tYXAucHVzaChba2V5LCB2YWx1ZV0pO1xuICAgICAgICB0aGlzLnNocmluaygpO1xuICAgIH1cblxuICAgIHByb3RlY3RlZCBzaHJpbmsoKSB7XG4gICAgICAgIGNvbnN0IG1heCA9IHRoaXMuX2hlYXAuZXh0cmFjdE1heCgpO1xuICAgICAgICBsZXQgaWR4ID0gdGhpcy5fbWFwLmxlbmd0aDtcbiAgICAgICAgd2hpbGUgKC0taWR4ID49IDApIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9tYXBbaWR4XVswXSA9PT0gbWF4KSB7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlkeCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgU21hbGxlc3ROOiBjb3VsZCBub3QgZmluZCBlbnRyeSBmb3Iga2V5ICR7bWF4fWApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuX21hcC5zcGxpY2UoaWR4LCAxKTtcbiAgICB9XG5cbiAgICBbU3ltYm9sLml0ZXJhdG9yXSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21hcFtTeW1ib2wuaXRlcmF0b3JdKCk7XG4gICAgfVxuXG4gICAgZW50cmllcygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21hcFtTeW1ib2wuaXRlcmF0b3JdO1xuICAgIH1cblxuICAgIGtleXMoKSB7XG4gICAgICAgIHJldHVybiBbLi4udGhpcy5faGVhcF07XG4gICAgfVxuXG4gICAgZ2V0IHNpemUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zaXplO1xuICAgIH1cblxuICAgIGNsZWFyKCkge1xuICAgICAgICB0aGlzLl9oZWFwLmNsZWFyKCk7XG4gICAgICAgIHRoaXMuX21hcCA9IFtdO1xuICAgIH1cblxuICAgIHNldFNpemUobmV3U2l6ZTogbnVtYmVyKSB7XG4gICAgICAgIHdoaWxlICh0aGlzLl9zaXplID4gbmV3U2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5zaHJpbmsoKTtcbiAgICAgICAgICAgIHRoaXMuX3NpemUtLTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLl9zaXplID0gbmV3U2l6ZTtcbiAgICB9XG59XG4iXX0=
\No newline at end of file