1670 lines
174 KiB
JavaScript
1670 lines
174 KiB
JavaScript
"use strict";
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
|
|
// src/index.ts
|
|
var src_exports = {};
|
|
__export(src_exports, {
|
|
AF_NIGHTCORE_RATE: () => AF_NIGHTCORE_RATE,
|
|
AF_VAPORWAVE_RATE: () => AF_VAPORWAVE_RATE,
|
|
AudioFilter: () => AudioFilter,
|
|
AudioFilters: () => AudioFilters,
|
|
BASS_EQ_BANDS: () => BASS_EQ_BANDS,
|
|
BiquadFilter: () => BiquadFilter,
|
|
BiquadStream: () => BiquadStream,
|
|
ChannelProcessor: () => ChannelProcessor,
|
|
Coefficients: () => Coefficients,
|
|
CompressorTransformer: () => CompressorTransformer,
|
|
Equalizer: () => Equalizer,
|
|
EqualizerCoefficients: () => EqualizerCoefficients,
|
|
EqualizerConfiguration: () => EqualizerConfiguration,
|
|
EqualizerStream: () => EqualizerStream,
|
|
FilterType: () => FilterType,
|
|
FiltersChain: () => FiltersChain,
|
|
Frequency: () => Frequency,
|
|
MonoStereoTransformer: () => MonoStereoTransformer,
|
|
PCMAudioTransformer: () => transformers_exports,
|
|
PCMResampler: () => PCMResampler,
|
|
PCMSeekerTransformer: () => PCMSeekerTransformer,
|
|
PCMTransformer: () => PCMTransformer,
|
|
Q_BUTTERWORTH: () => Q_BUTTERWORTH,
|
|
ReverbTransformer: () => ReverbTransformer,
|
|
VolumeTransformer: () => VolumeTransformer,
|
|
version: () => version
|
|
});
|
|
module.exports = __toCommonJS(src_exports);
|
|
|
|
// src/biquad/Coefficients.ts
|
|
var FilterType = {
|
|
SinglePoleLowPassApprox: 0,
|
|
SinglePoleLowPass: 1,
|
|
LowPass: 2,
|
|
HighPass: 3,
|
|
BandPass: 4,
|
|
Notch: 5,
|
|
AllPass: 6,
|
|
LowShelf: 7,
|
|
HighShelf: 8,
|
|
PeakingEQ: 9
|
|
};
|
|
var Q_BUTTERWORTH = Math.SQRT1_2;
|
|
var _Coefficients = class _Coefficients {
|
|
constructor(data) {
|
|
// Denominator coefficients
|
|
__publicField(this, "a1", 0);
|
|
__publicField(this, "a2", 0);
|
|
// Nominator coefficients
|
|
__publicField(this, "b0", 0);
|
|
__publicField(this, "b1", 0);
|
|
__publicField(this, "b2", 0);
|
|
if (data) {
|
|
this.a1 = data.a1;
|
|
this.a2 = data.a2;
|
|
this.b0 = data.b0;
|
|
this.b1 = data.b1;
|
|
this.b2 = data.b2;
|
|
}
|
|
}
|
|
static from(filter, samplingFreq, cutoffFreq, Q, dbGain = -10) {
|
|
if (2 * cutoffFreq > samplingFreq) {
|
|
throw new Error(`Cutoff frequency is too big!`);
|
|
}
|
|
if (Q < 0) {
|
|
throw new Error(`Q may not be negative`);
|
|
}
|
|
const omega = 2 * Math.PI * cutoffFreq / samplingFreq;
|
|
const bqf = typeof filter === "string" ? FilterType[filter] : filter;
|
|
switch (bqf) {
|
|
case FilterType.SinglePoleLowPassApprox: {
|
|
const alpha = omega / (omega + 1);
|
|
return new _Coefficients({
|
|
a1: alpha - 1,
|
|
a2: 0,
|
|
b0: alpha,
|
|
b1: 0,
|
|
b2: 0
|
|
});
|
|
}
|
|
case FilterType.SinglePoleLowPass: {
|
|
const omega_t = Math.tan(omega / 2);
|
|
const a0 = 1 + omega_t;
|
|
return new _Coefficients({
|
|
a1: (omega_t - 1) / a0,
|
|
a2: 0,
|
|
b0: omega_t / a0,
|
|
b1: omega_t / a0,
|
|
b2: 0
|
|
});
|
|
}
|
|
case FilterType.LowPass: {
|
|
const omega_s = Math.sin(omega);
|
|
const omega_c = Math.cos(omega);
|
|
const alpha = omega_s / (2 * Q);
|
|
const b0 = (1 - omega_c) * 0.5;
|
|
const b1 = 1 - omega_c;
|
|
const b2 = (1 - omega_c) * 0.5;
|
|
const a0 = 1 + alpha;
|
|
const a1 = -2 * omega_c;
|
|
const a2 = 1 - alpha;
|
|
const div = 1 / a0;
|
|
return new _Coefficients({
|
|
a1: a1 * div,
|
|
a2: a2 * div,
|
|
b0: b0 * div,
|
|
b1: b1 * div,
|
|
b2: b2 * div
|
|
});
|
|
}
|
|
case FilterType.HighPass: {
|
|
const omega_s = Math.sin(omega);
|
|
const omega_c = Math.cos(omega);
|
|
const alpha = omega_s / (2 * Q);
|
|
const b0 = (1 + omega_c) * 0.5;
|
|
const b1 = -(1 + omega_c);
|
|
const b2 = (1 + omega_c) * 0.5;
|
|
const a0 = 1 + alpha;
|
|
const a1 = -2 * omega_c;
|
|
const a2 = 1 - alpha;
|
|
const div = 1 / a0;
|
|
return new _Coefficients({
|
|
a1: a1 * div,
|
|
a2: a2 * div,
|
|
b0: b0 * div,
|
|
b1: b1 * div,
|
|
b2: b2 * div
|
|
});
|
|
}
|
|
case FilterType.Notch: {
|
|
const omega_s = Math.sin(omega);
|
|
const omega_c = Math.cos(omega);
|
|
const alpha = omega_s / (2 * Q);
|
|
const b0 = 1;
|
|
const b1 = -2 * omega_c;
|
|
const b2 = 1;
|
|
const a0 = 1 + alpha;
|
|
const a1 = -2 * omega_c;
|
|
const a2 = 1 - alpha;
|
|
const div = 1 / a0;
|
|
return new _Coefficients({
|
|
a1: a1 * div,
|
|
a2: a2 * div,
|
|
b0: b0 * div,
|
|
b1: b1 * div,
|
|
b2: b2 * div
|
|
});
|
|
}
|
|
case FilterType.BandPass: {
|
|
const omega_s = Math.sin(omega);
|
|
const omega_c = Math.cos(omega);
|
|
const alpha = omega_s / (2 * Q);
|
|
const b0 = omega_s / 2;
|
|
const b1 = 0;
|
|
const b2 = -(omega_s / 2);
|
|
const a0 = 1 + alpha;
|
|
const a1 = -2 * omega_c;
|
|
const a2 = 1 - alpha;
|
|
const div = 1 / a0;
|
|
return new _Coefficients({
|
|
a1: a1 * div,
|
|
a2: a2 * div,
|
|
b0: b0 * div,
|
|
b1: b1 * div,
|
|
b2: b2 * div
|
|
});
|
|
}
|
|
case FilterType.AllPass: {
|
|
const omega_s = Math.sin(omega);
|
|
const omega_c = Math.cos(omega);
|
|
const alpha = omega_s / (2 * Q);
|
|
const b0 = 1 - alpha;
|
|
const b1 = -2 * omega_c;
|
|
const b2 = 1 + alpha;
|
|
const a0 = 1 + alpha;
|
|
const a1 = -2 * omega_c;
|
|
const a2 = 1 - alpha;
|
|
return new _Coefficients({
|
|
a1: a1 / a0,
|
|
a2: a2 / a0,
|
|
b0: b0 / a0,
|
|
b1: b1 / a0,
|
|
b2: b2 / a0
|
|
});
|
|
}
|
|
case FilterType.LowShelf: {
|
|
const a = Math.pow(10, dbGain / 40);
|
|
const omega_s = Math.sin(omega);
|
|
const omega_c = Math.cos(omega);
|
|
const alpha = omega_s / (2 * Q);
|
|
const b0 = a * (a + 1 - (a - 1) * omega_c + 2 * alpha * Math.sqrt(a));
|
|
const b1 = 2 * a * (a - 1 - (a + 1) * omega_c);
|
|
const b2 = a * (a + 1 - (a - 1) * omega_c - 2 * alpha * Math.sqrt(a));
|
|
const a0 = a + 1 + (a - 1) * omega_c + 2 * alpha * Math.sqrt(a);
|
|
const a1 = -2 * (a - 1 + (a + 1) * omega_c);
|
|
const a2 = a + 1 + (a - 1) * omega_c - 2 * alpha * Math.sqrt(a);
|
|
return new _Coefficients({
|
|
a1: a1 / a0,
|
|
a2: a2 / a0,
|
|
b0: b0 / a0,
|
|
b1: b1 / a0,
|
|
b2: b2 / a0
|
|
});
|
|
}
|
|
case FilterType.HighShelf: {
|
|
const a = Math.pow(10, dbGain / 40);
|
|
const omega_s = Math.sin(omega);
|
|
const omega_c = Math.cos(omega);
|
|
const alpha = omega_s / (2 * Q);
|
|
const b0 = a * (a + 1 + (a - 1) * omega_c + 2 * alpha * Math.sqrt(a));
|
|
const b1 = -2 * a * (a - 1 + (a + 1) * omega_c);
|
|
const b2 = a * (a + 1 + (a - 1) * omega_c - 2 * alpha * Math.sqrt(a));
|
|
const a0 = a + 1 - (a - 1) * omega_c + 2 * alpha * Math.sqrt(a);
|
|
const a1 = 2 * (a - 1 - (a + 1) * omega_c);
|
|
const a2 = a + 1 - (a - 1) * omega_c - 2 * alpha * Math.sqrt(a);
|
|
return new _Coefficients({
|
|
a1: a1 / a0,
|
|
a2: a2 / a0,
|
|
b0: b0 / a0,
|
|
b1: b1 / a0,
|
|
b2: b2 / a0
|
|
});
|
|
}
|
|
case FilterType.PeakingEQ: {
|
|
const a = Math.pow(10, dbGain / 40);
|
|
const omega_s = Math.sin(omega);
|
|
const omega_c = Math.cos(omega);
|
|
const alpha = omega_s / (2 * Q);
|
|
const b0 = 1 + alpha * a;
|
|
const b1 = -2 * omega_c;
|
|
const b2 = 1 - alpha * a;
|
|
const a0 = 1 + alpha / a;
|
|
const a1 = -2 * omega_c;
|
|
const a2 = 1 - alpha / a;
|
|
return new _Coefficients({
|
|
a1: a1 / a0,
|
|
a2: a2 / a0,
|
|
b0: b0 / a0,
|
|
b1: b1 / a0,
|
|
b2: b2 / a0
|
|
});
|
|
}
|
|
default:
|
|
throw new TypeError(`Invalid filter type "${filter}"`);
|
|
}
|
|
}
|
|
};
|
|
__name(_Coefficients, "Coefficients");
|
|
var Coefficients = _Coefficients;
|
|
|
|
// src/biquad/Biquad.ts
|
|
var _BiquadFilter = class _BiquadFilter {
|
|
constructor(coefficients) {
|
|
this.coefficients = coefficients;
|
|
__publicField(this, "x1", 0);
|
|
__publicField(this, "x2", 0);
|
|
__publicField(this, "y1", 0);
|
|
__publicField(this, "y2", 0);
|
|
__publicField(this, "s1", 0);
|
|
__publicField(this, "s2", 0);
|
|
}
|
|
setFilter(filter, options) {
|
|
const coefficients = Coefficients.from(
|
|
filter,
|
|
options.fs,
|
|
options.f0,
|
|
options.Q,
|
|
options.gain
|
|
);
|
|
this.update(coefficients);
|
|
}
|
|
update(coefficients) {
|
|
this.coefficients = coefficients;
|
|
}
|
|
replace(coefficients) {
|
|
this.coefficients = coefficients;
|
|
}
|
|
reset() {
|
|
this.x1 = 0;
|
|
this.x2 = 0;
|
|
this.y1 = 0;
|
|
this.y2 = 0;
|
|
this.s1 = 0;
|
|
this.s2 = 0;
|
|
}
|
|
run(input) {
|
|
const { a1, a2, b0, b1, b2 } = this.coefficients;
|
|
const out = b0 * input + b1 * this.x1 + b2 * this.x2 - a1 * this.y1 - a2 * this.y2;
|
|
this.x2 = this.x1;
|
|
this.x1 = input;
|
|
this.y2 = this.y1;
|
|
this.y1 = out;
|
|
return out;
|
|
}
|
|
runTransposed(input) {
|
|
const { a1, a2, b0, b1, b2 } = this.coefficients;
|
|
const out = this.s1 + b0 * input;
|
|
this.s1 = this.s2 + b1 * input - a1 * out;
|
|
this.s2 = b2 * input - a2 * out;
|
|
return out;
|
|
}
|
|
};
|
|
__name(_BiquadFilter, "BiquadFilter");
|
|
var BiquadFilter = _BiquadFilter;
|
|
|
|
// src/utils/Frequency.ts
|
|
var _Frequency = class _Frequency {
|
|
constructor(__val) {
|
|
this.__val = __val;
|
|
if (typeof __val !== "number" || isNaN(__val) || __val === Infinity)
|
|
throw new TypeError("Frequency value must be a number");
|
|
if (this.__val < 0)
|
|
throw new Error(`Frequency value cannot be negative (${__val})`);
|
|
}
|
|
khz() {
|
|
return this.__val * 1e3;
|
|
}
|
|
mhz() {
|
|
return this.__val * 1e6;
|
|
}
|
|
hz() {
|
|
return this.__val;
|
|
}
|
|
dt() {
|
|
return 1 / this.__val;
|
|
}
|
|
valueOf() {
|
|
return this.__val;
|
|
}
|
|
toString() {
|
|
return `${this.__val}Hz`;
|
|
}
|
|
toJSON() {
|
|
return this.toString();
|
|
}
|
|
};
|
|
__name(_Frequency, "Frequency");
|
|
var Frequency = _Frequency;
|
|
|
|
// src/utils/PCMTransformer.ts
|
|
var import_stream = require("stream");
|
|
var _PCMTransformer = class _PCMTransformer extends import_stream.Transform {
|
|
constructor(options = {}) {
|
|
super(options);
|
|
__publicField(this, "type", "s16le");
|
|
__publicField(this, "bits");
|
|
__publicField(this, "bytes");
|
|
__publicField(this, "extremum");
|
|
__publicField(this, "disabled", false);
|
|
__publicField(this, "sampleRate", 48e3);
|
|
__publicField(this, "onUpdate", /* @__PURE__ */ __name(() => {
|
|
}, "onUpdate"));
|
|
options.type ?? (options.type = "s16le");
|
|
this.disabled = !!options.disabled;
|
|
if (typeof options.sampleRate === "number" && options.sampleRate > 0) {
|
|
this.sampleRate = options.sampleRate;
|
|
}
|
|
switch (options.type) {
|
|
case "s16be":
|
|
case "s16le":
|
|
this.type = options.type;
|
|
this.bits = 16;
|
|
break;
|
|
case "s32be":
|
|
case "s32le":
|
|
this.type = options.type;
|
|
this.bits = 32;
|
|
break;
|
|
default:
|
|
throw new TypeError(
|
|
`Expected type to be one of ${["s16be", "s16le", "s32be", "s32le"].join(", ")}, got "${options.type}"`
|
|
);
|
|
}
|
|
this.bytes = this.bits / 8;
|
|
this.extremum = Math.pow(2, this.bits - 1);
|
|
}
|
|
disable() {
|
|
this.disabled = true;
|
|
}
|
|
enable() {
|
|
this.disabled = false;
|
|
}
|
|
toggle() {
|
|
this.disabled = !this.disabled;
|
|
return this.disabled;
|
|
}
|
|
_readInt(buffer, index) {
|
|
const method = `readInt${this.type.substring(1).toUpperCase()}`;
|
|
return buffer[method](index);
|
|
}
|
|
_writeInt(buffer, int, index) {
|
|
const method = `writeInt${this.type.substring(1).toUpperCase()}`;
|
|
return buffer[method](int, index);
|
|
}
|
|
clamp(val, max = this.extremum - 1, min = -this.extremum) {
|
|
return Math.min(max, Math.max(min, val));
|
|
}
|
|
setSampleRate(rate) {
|
|
this.sampleRate = rate;
|
|
return;
|
|
}
|
|
};
|
|
__name(_PCMTransformer, "PCMTransformer");
|
|
var PCMTransformer = _PCMTransformer;
|
|
|
|
// src/biquad/BiquadStream.ts
|
|
var _BiquadStream = class _BiquadStream extends PCMTransformer {
|
|
constructor(options = {}) {
|
|
super(options);
|
|
__publicField(this, "biquad");
|
|
__publicField(this, "cutoff", 80);
|
|
__publicField(this, "gain", 0);
|
|
__publicField(this, "biquadFilter");
|
|
__publicField(this, "Q", Q_BUTTERWORTH);
|
|
if ("cutoff" in options) this.cutoff = options.cutoff;
|
|
if ("gain" in options) this.gain = options.gain;
|
|
if ("Q" in options) this.Q = options.Q;
|
|
if ("biquadFilter" in options) {
|
|
if (typeof options.biquadFilter === "string" || typeof options.biquadFilter === "number")
|
|
this.biquadFilter = options.filter;
|
|
if (this.biquadFilter != null) {
|
|
this.biquad = new BiquadFilter(
|
|
Coefficients.from(
|
|
this.biquadFilter,
|
|
this.sampleRate,
|
|
this.cutoff,
|
|
this.Q,
|
|
this.gain
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
get filters() {
|
|
return this.biquadFilter;
|
|
}
|
|
set filters(f) {
|
|
if (f == null || typeof f === "string" || typeof f === "number") {
|
|
this.update({ filter: f });
|
|
} else {
|
|
throw new TypeError(`Invalid biquad filter type "${f}"`);
|
|
}
|
|
}
|
|
getFilterName() {
|
|
if (this.biquadFilter == null) return null;
|
|
if (typeof this.biquadFilter === "string") return this.biquadFilter;
|
|
return Object.entries(FilterType).find(
|
|
(r) => r[1] === this.biquadFilter
|
|
)?.[0];
|
|
}
|
|
update(options) {
|
|
if ("cutoff" in options) this.cutoff = options.cutoff;
|
|
if ("gain" in options) this.gain = options.gain;
|
|
if ("Q" in options) this.Q = options.Q;
|
|
if ("filter" in options) this.biquadFilter = options.filter;
|
|
if (this.biquadFilter != null) {
|
|
this.biquad = new BiquadFilter(
|
|
Coefficients.from(
|
|
this.biquadFilter,
|
|
this.sampleRate,
|
|
this.cutoff,
|
|
this.Q,
|
|
this.gain
|
|
)
|
|
);
|
|
}
|
|
this.onUpdate?.();
|
|
}
|
|
setFilter(filter) {
|
|
this.update({ filter });
|
|
}
|
|
setQ(Q) {
|
|
this.update({ Q });
|
|
}
|
|
setCutoff(f0) {
|
|
this.update({ cutoff: f0 });
|
|
}
|
|
setGain(dB) {
|
|
this.update({ gain: dB });
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
if (this.disabled || !this.biquad) {
|
|
this.push(chunk);
|
|
return callback();
|
|
}
|
|
const endIndex = Math.floor(chunk.length / 2) * 2;
|
|
const { bytes } = this;
|
|
for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {
|
|
const int = this._readInt(chunk, sampleIndex);
|
|
const result = this.biquad.run(int);
|
|
this._writeInt(chunk, this.clamp(result), sampleIndex);
|
|
}
|
|
this.push(chunk);
|
|
return callback();
|
|
}
|
|
};
|
|
__name(_BiquadStream, "BiquadStream");
|
|
var BiquadStream = _BiquadStream;
|
|
|
|
// src/equalizer/ChannelProcessor.ts
|
|
var _ChannelProcessor = class _ChannelProcessor {
|
|
constructor(bandMultipliers) {
|
|
__publicField(this, "history");
|
|
__publicField(this, "bandMultipliers");
|
|
__publicField(this, "current");
|
|
__publicField(this, "m1");
|
|
__publicField(this, "m2");
|
|
this.history = new Array(Equalizer.BAND_COUNT * 6).fill(0);
|
|
this.bandMultipliers = bandMultipliers;
|
|
this.current = 0;
|
|
this.m1 = 2;
|
|
this.m2 = 1;
|
|
}
|
|
processInt(int) {
|
|
let result = int * 0.25;
|
|
for (let bandIndex = 0; bandIndex < Equalizer.BAND_COUNT; bandIndex++) {
|
|
const x = bandIndex * 6;
|
|
const y = x + 3;
|
|
const coefficients = Equalizer.Coefficients48000[bandIndex];
|
|
const bandResult = coefficients.alpha * (int - this.history[x + this.m2]) + coefficients.gamma * this.history[y + this.m1] - coefficients.beta * this.history[y + this.m2];
|
|
this.history[x + this.current] = int;
|
|
this.history[y + this.current] = bandResult;
|
|
result += bandResult * this.bandMultipliers[bandIndex];
|
|
}
|
|
const val = result * 4;
|
|
return val;
|
|
}
|
|
process(samples, extremum = 131072, bytes = 2, readInt, writeInt) {
|
|
const endIndex = Math.floor(samples.length / 2) * 2;
|
|
for (let sampleIndex = 0; sampleIndex < endIndex; sampleIndex += bytes) {
|
|
const sample = readInt?.(samples, sampleIndex) ?? samples.readInt16LE(sampleIndex);
|
|
const result = this.processInt(sample);
|
|
const val = Math.min(extremum - 1, Math.max(-extremum, result));
|
|
writeInt?.(samples, val, sampleIndex) ?? samples.writeInt16LE(val, sampleIndex);
|
|
this.step();
|
|
}
|
|
return samples;
|
|
}
|
|
step() {
|
|
if (++this.current === 3) {
|
|
this.current = 0;
|
|
}
|
|
if (++this.m1 === 3) {
|
|
this.m1 = 0;
|
|
}
|
|
if (++this.m2 === 3) {
|
|
this.m2 = 0;
|
|
}
|
|
}
|
|
reset() {
|
|
this.history.fill(0);
|
|
}
|
|
};
|
|
__name(_ChannelProcessor, "ChannelProcessor");
|
|
var ChannelProcessor = _ChannelProcessor;
|
|
|
|
// src/equalizer/Coefficients.ts
|
|
var _EqualizerCoefficients = class _EqualizerCoefficients {
|
|
constructor(beta, alpha, gamma) {
|
|
this.beta = beta;
|
|
this.alpha = alpha;
|
|
this.gamma = gamma;
|
|
}
|
|
setBeta(v) {
|
|
this.beta = v;
|
|
}
|
|
setAlpha(v) {
|
|
this.alpha = v;
|
|
}
|
|
setGamma(v) {
|
|
this.gamma = v;
|
|
}
|
|
toJSON() {
|
|
const { alpha, beta, gamma } = this;
|
|
return { alpha, beta, gamma };
|
|
}
|
|
};
|
|
__name(_EqualizerCoefficients, "EqualizerCoefficients");
|
|
var EqualizerCoefficients = _EqualizerCoefficients;
|
|
|
|
// src/equalizer/EqualizerConfiguration.ts
|
|
var _EqualizerConfiguration = class _EqualizerConfiguration {
|
|
constructor(bandMultipliers) {
|
|
this.bandMultipliers = bandMultipliers;
|
|
}
|
|
setGain(band, value) {
|
|
if (this.isValidBand(band)) {
|
|
this.bandMultipliers[band] = Math.max(Math.min(value, 1), -0.25);
|
|
}
|
|
}
|
|
getGain(band) {
|
|
if (this.isValidBand(band)) {
|
|
return this.bandMultipliers[band];
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
isValidBand(band) {
|
|
return band >= 0 && band < this.bandMultipliers.length;
|
|
}
|
|
};
|
|
__name(_EqualizerConfiguration, "EqualizerConfiguration");
|
|
var EqualizerConfiguration = _EqualizerConfiguration;
|
|
|
|
// src/equalizer/Equalizer.ts
|
|
var _Equalizer = class _Equalizer extends EqualizerConfiguration {
|
|
constructor(channelCount, bandMultipliers) {
|
|
super(bandMultipliers);
|
|
__publicField(this, "channels", []);
|
|
__publicField(this, "channelCount");
|
|
this.channelCount = channelCount;
|
|
this.channels = this.createChannelProcessor();
|
|
}
|
|
createChannelProcessor() {
|
|
return Array.from({ length: this.channelCount }, () => {
|
|
return new ChannelProcessor(this.bandMultipliers);
|
|
});
|
|
}
|
|
process(input) {
|
|
return this.channels.map((c, i) => {
|
|
const { data, extremum, readInt, writeInt, bytes } = input[i];
|
|
return c.process(data, extremum, bytes, readInt, writeInt);
|
|
});
|
|
}
|
|
};
|
|
__name(_Equalizer, "Equalizer");
|
|
__publicField(_Equalizer, "BAND_COUNT", 15);
|
|
__publicField(_Equalizer, "SAMPLE_RATE", 48e3);
|
|
__publicField(_Equalizer, "Coefficients48000", [
|
|
new EqualizerCoefficients(0.99847546664, 76226668143e-14, 1.9984647656),
|
|
new EqualizerCoefficients(0.99756184654, 0.0012190767289, 1.9975344645),
|
|
new EqualizerCoefficients(0.99616261379, 0.0019186931041, 1.9960947369),
|
|
new EqualizerCoefficients(0.99391578543, 0.0030421072865, 1.9937449618),
|
|
new EqualizerCoefficients(0.99028307215, 0.0048584639242, 1.9898465702),
|
|
new EqualizerCoefficients(0.98485897264, 0.0075705136795, 1.9837962543),
|
|
new EqualizerCoefficients(0.97588512657, 0.012057436715, 1.9731772447),
|
|
new EqualizerCoefficients(0.96228521814, 0.018857390928, 1.9556164694),
|
|
new EqualizerCoefficients(0.94080933132, 0.029595334338, 1.9242054384),
|
|
new EqualizerCoefficients(0.90702059196, 0.046489704022, 1.8653476166),
|
|
new EqualizerCoefficients(0.85868004289, 0.070659978553, 1.7600401337),
|
|
new EqualizerCoefficients(0.78409610788, 0.10795194606, 1.5450725522),
|
|
new EqualizerCoefficients(0.68332861002, 0.15833569499, 1.1426447155),
|
|
new EqualizerCoefficients(
|
|
0.55267518228,
|
|
0.22366240886,
|
|
0.40186190803
|
|
),
|
|
new EqualizerCoefficients(
|
|
0.41811888447,
|
|
0.29094055777,
|
|
-0.70905944223
|
|
)
|
|
]);
|
|
var Equalizer = _Equalizer;
|
|
|
|
// src/equalizer/EqualizerStream.ts
|
|
var _EqualizerStream = class _EqualizerStream extends PCMTransformer {
|
|
constructor(options) {
|
|
super(options);
|
|
__publicField(this, "bandMultipliers", new Array(Equalizer.BAND_COUNT).fill(0));
|
|
__publicField(this, "equalizer");
|
|
options = Object.assign(
|
|
{},
|
|
{
|
|
bandMultiplier: [],
|
|
channels: 1
|
|
},
|
|
options || {}
|
|
);
|
|
this.equalizer = new Equalizer(options.channels || 1, this.bandMultipliers);
|
|
if (Array.isArray(options.bandMultiplier))
|
|
this._processBands(options.bandMultiplier);
|
|
}
|
|
_processBands(multiplier) {
|
|
for (const mul of multiplier) {
|
|
if (mul.band > Equalizer.BAND_COUNT - 1 || mul.band < 0)
|
|
throw new RangeError(
|
|
`Band value out of range. Expected >0 & <${Equalizer.BAND_COUNT - 1}, received "${mul.band}"`
|
|
);
|
|
this.equalizer.setGain(mul.band, mul.gain);
|
|
}
|
|
this.onUpdate?.();
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
if (this.disabled) {
|
|
this.push(chunk);
|
|
return callback();
|
|
}
|
|
this.equalizer.process(
|
|
[
|
|
{
|
|
data: chunk,
|
|
extremum: this.extremum,
|
|
readInt: /* @__PURE__ */ __name((b, idx) => this._readInt(b, idx), "readInt"),
|
|
writeInt: /* @__PURE__ */ __name((b, i, idx) => this._writeInt(b, i, idx), "writeInt"),
|
|
bytes: this.bytes
|
|
}
|
|
]
|
|
);
|
|
this.push(chunk);
|
|
return callback();
|
|
}
|
|
getEQ() {
|
|
return this.bandMultipliers.map((m, i) => ({
|
|
band: i,
|
|
gain: m
|
|
}));
|
|
}
|
|
setEQ(bands) {
|
|
this._processBands(bands);
|
|
}
|
|
resetEQ() {
|
|
this._processBands(
|
|
Array.from(
|
|
{
|
|
length: Equalizer.BAND_COUNT
|
|
},
|
|
(_, i) => ({
|
|
band: i,
|
|
gain: 0
|
|
})
|
|
)
|
|
);
|
|
}
|
|
};
|
|
__name(_EqualizerStream, "EqualizerStream");
|
|
var EqualizerStream = _EqualizerStream;
|
|
|
|
// src/audio/MonoStereoTransformer.ts
|
|
var _MonoStereoTransformer = class _MonoStereoTransformer extends PCMTransformer {
|
|
constructor(options) {
|
|
super(options);
|
|
__publicField(this, "strategy");
|
|
if (!["m2s", "s2m"].includes(options?.strategy)) {
|
|
throw new TypeError(`Strategy must be "m2s" or "s2m"`);
|
|
}
|
|
this.strategy = options.strategy;
|
|
}
|
|
setStrategy(strategy) {
|
|
this.strategy = strategy;
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
if (this.disabled) {
|
|
this.push(chunk);
|
|
return callback();
|
|
}
|
|
const len = Math.floor(chunk.length / 2) * 2;
|
|
if (this.strategy === "m2s") {
|
|
this.push(this.toStereo(chunk, len));
|
|
} else {
|
|
this.push(this.toMono(chunk, len));
|
|
}
|
|
return callback();
|
|
}
|
|
toStereo(sample, len) {
|
|
const bytes = this.bytes;
|
|
const stereoBuffer = Buffer.alloc(len * 2);
|
|
for (let i = 0; i < len; i += bytes) {
|
|
stereoBuffer[i * 2 + 0] = sample[i];
|
|
stereoBuffer[i * 2 + 1] = sample[i + 1];
|
|
stereoBuffer[i * 2 + 2] = sample[i];
|
|
stereoBuffer[i * 2 + 3] = sample[i + 1];
|
|
}
|
|
return stereoBuffer;
|
|
}
|
|
toMono(sample, len) {
|
|
const bytes = this.bytes;
|
|
const monoBuffer = Buffer.alloc(Math.floor(len / 2));
|
|
for (let i = 0; i < len; i += bytes) {
|
|
monoBuffer[i] = sample[i * 2 + 0];
|
|
monoBuffer[i + 1] = sample[i * 2 + 1];
|
|
}
|
|
return monoBuffer;
|
|
}
|
|
};
|
|
__name(_MonoStereoTransformer, "MonoStereoTransformer");
|
|
var MonoStereoTransformer = _MonoStereoTransformer;
|
|
|
|
// src/audio/transformers/index.ts
|
|
var transformers_exports = {};
|
|
__export(transformers_exports, {
|
|
applyBiquad: () => applyBiquad,
|
|
applyEqualization: () => applyEqualization,
|
|
applyPulsator: () => applyPulsator,
|
|
applyTremolo: () => applyTremolo,
|
|
applyVibrato: () => applyVibrato,
|
|
applyVolume: () => applyVolume
|
|
});
|
|
|
|
// src/audio/transformers/biquad.ts
|
|
function applyBiquad(filterer, int) {
|
|
return filterer.run(int);
|
|
}
|
|
__name(applyBiquad, "applyBiquad");
|
|
|
|
// src/audio/transformers/dsp.ts
|
|
function applyPulsator(config, int, channel) {
|
|
const sin = Math.sin(config.x);
|
|
const currentChannelVal = channel === 0 ? sin : -sin;
|
|
const res = int * (currentChannelVal + 1) / 2;
|
|
config.x += config.dI;
|
|
return res;
|
|
}
|
|
__name(applyPulsator, "applyPulsator");
|
|
function applyTremolo(config, int, sampleRate) {
|
|
const fOffset = 1 - config.depth;
|
|
const modSignal = fOffset + config.depth * Math.sin(config.phase);
|
|
config.phase += 2 * Math.PI / sampleRate * config.frequency;
|
|
return modSignal * int;
|
|
}
|
|
__name(applyTremolo, "applyTremolo");
|
|
function applyVibrato(config, int, sampleRate) {
|
|
const fOffset = 1 - config.depth;
|
|
const modSignal = fOffset + config.depth * Math.sin(2 * Math.PI * config.phase);
|
|
config.phase += 2 * Math.PI / sampleRate * config.frequency;
|
|
return modSignal * int;
|
|
}
|
|
__name(applyVibrato, "applyVibrato");
|
|
function applyVolume(vol, int) {
|
|
return vol * int;
|
|
}
|
|
__name(applyVolume, "applyVolume");
|
|
|
|
// src/audio/transformers/equalizer.ts
|
|
function applyEqualization(eq, int) {
|
|
const processor = eq.channels[0];
|
|
const result = processor.processInt(int);
|
|
processor.step();
|
|
return result;
|
|
}
|
|
__name(applyEqualization, "applyEqualization");
|
|
|
|
// src/audio/AudioFilter.ts
|
|
var AudioFilters = {
|
|
"8D": "8D",
|
|
Tremolo: "Tremolo",
|
|
Vibrato: "Vibrato"
|
|
};
|
|
var AF_NIGHTCORE_RATE = 1.3;
|
|
var AF_VAPORWAVE_RATE = 0.8;
|
|
var BASS_EQ_BANDS = Array.from(
|
|
{ length: 3 },
|
|
(_, i) => ({
|
|
band: i,
|
|
gain: 0.25
|
|
})
|
|
);
|
|
var _AudioFilter = class _AudioFilter extends PCMTransformer {
|
|
constructor(options) {
|
|
super(options);
|
|
__publicField(this, "filters", []);
|
|
__publicField(this, "targetSampleRate", this.sampleRate);
|
|
__publicField(this, "pulsatorConfig", {
|
|
hz: 0.02,
|
|
x: 0,
|
|
dI: 3926990816987241e-21
|
|
});
|
|
__publicField(this, "tremoloConfig", {
|
|
phase: 0,
|
|
depth: 0.5,
|
|
frequency: 5
|
|
});
|
|
__publicField(this, "vibratoConfig", {
|
|
phase: 0,
|
|
depth: 0.5,
|
|
frequency: 5
|
|
});
|
|
if (options && Array.isArray(options.filters)) {
|
|
this.setFilters(options.filters);
|
|
}
|
|
this.onUpdate?.();
|
|
}
|
|
setTargetSampleRate(rate) {
|
|
this.targetSampleRate = rate || this.sampleRate;
|
|
return;
|
|
}
|
|
setPulsator(hz) {
|
|
hz /= 4;
|
|
this.pulsatorConfig.hz = hz;
|
|
const samplesPerCycle = this.targetSampleRate / (hz * 2 * Math.PI);
|
|
this.pulsatorConfig.dI = hz === 0 ? 0 : 1 / samplesPerCycle;
|
|
this.onUpdate?.();
|
|
}
|
|
get pulsator() {
|
|
return this.pulsatorConfig.hz;
|
|
}
|
|
setTremolo({
|
|
depth = this.tremoloConfig.depth,
|
|
frequency = this.tremoloConfig.frequency,
|
|
phase = this.tremoloConfig.phase
|
|
}) {
|
|
if (typeof depth === "number") this.tremoloConfig.depth = depth;
|
|
if (typeof frequency === "number") this.tremoloConfig.frequency = frequency;
|
|
if (typeof phase === "number") this.tremoloConfig.phase = phase;
|
|
this.onUpdate?.();
|
|
}
|
|
setVibrato({
|
|
depth = this.vibratoConfig.depth,
|
|
frequency = this.vibratoConfig.frequency,
|
|
phase = this.vibratoConfig.phase
|
|
}) {
|
|
if (typeof depth === "number") this.vibratoConfig.depth = depth;
|
|
if (typeof frequency === "number") this.vibratoConfig.frequency = frequency;
|
|
if (typeof phase === "number") this.vibratoConfig.phase = phase;
|
|
this.onUpdate?.();
|
|
}
|
|
get tremolo() {
|
|
return this.tremoloConfig;
|
|
}
|
|
setFilters(filters) {
|
|
if (!Array.isArray(filters) || !filters.every((r) => r in AudioFilters)) {
|
|
return false;
|
|
}
|
|
this.filters = filters;
|
|
this.onUpdate?.();
|
|
return true;
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
if (this.disabled || !this.filters.length) {
|
|
return callback(null, chunk);
|
|
}
|
|
const len = Math.floor(chunk.length / 2) * 2;
|
|
const { bytes } = this;
|
|
let L = false;
|
|
for (let i = 0; i < len; i += bytes) {
|
|
const int = this._readInt(chunk, i);
|
|
const value = this.applyFilters(int, +(L = !L));
|
|
this._writeInt(chunk, this.clamp(value), i);
|
|
}
|
|
this.push(chunk);
|
|
return callback();
|
|
}
|
|
get currentSampleRate() {
|
|
return this.targetSampleRate || this.sampleRate;
|
|
}
|
|
applyFilters(byte, channel) {
|
|
if (this.filters.length) {
|
|
for (const filter of this.filters) {
|
|
if (filter === "8D") {
|
|
byte = applyPulsator(this.pulsatorConfig, byte, channel);
|
|
}
|
|
if (filter === "Tremolo") {
|
|
byte = applyTremolo(this.tremoloConfig, byte, this.currentSampleRate);
|
|
}
|
|
if (filter === "Vibrato") {
|
|
byte = applyVibrato(this.vibratoConfig, byte, this.currentSampleRate);
|
|
}
|
|
}
|
|
}
|
|
return byte;
|
|
}
|
|
};
|
|
__name(_AudioFilter, "AudioFilter");
|
|
var AudioFilter = _AudioFilter;
|
|
|
|
// src/audio/PCMResampler.ts
|
|
var _PCMResampler = class _PCMResampler extends PCMTransformer {
|
|
constructor(options) {
|
|
super(options);
|
|
__publicField(this, "inputSampleRate");
|
|
__publicField(this, "channels");
|
|
__publicField(this, "buffer");
|
|
__publicField(this, "currentFilter", null);
|
|
this.inputSampleRate = options?.inputSampleRate ?? 48e3;
|
|
this.channels = options?.channels ?? 2;
|
|
this.buffer = Buffer.alloc(0);
|
|
if (this.inputSampleRate < 1) {
|
|
this.inputSampleRate = 48e3;
|
|
}
|
|
if (options?.targetSampleRate) {
|
|
this.setSampleRate(options?.targetSampleRate);
|
|
}
|
|
}
|
|
setFilter(filter) {
|
|
if (this.currentFilter === filter) return;
|
|
switch (filter) {
|
|
case "nightcore":
|
|
this.setSampleRate(this.inputSampleRate * 1.25);
|
|
break;
|
|
case "vaporwave":
|
|
this.setSampleRate(this.inputSampleRate * 0.8);
|
|
break;
|
|
default:
|
|
this.setSampleRate(this.inputSampleRate);
|
|
break;
|
|
}
|
|
this.currentFilter = filter;
|
|
}
|
|
getParameters() {
|
|
return {
|
|
currentFilter: this.currentFilter,
|
|
inputSampleRate: this.inputSampleRate,
|
|
channels: this.channels,
|
|
sampleRate: this.sampleRate
|
|
};
|
|
}
|
|
toggleFilter(filter) {
|
|
const same = this.currentFilter === filter;
|
|
this.setFilter(same ? null : filter);
|
|
return !same;
|
|
}
|
|
getRatio() {
|
|
if (this.inputSampleRate === 0) return 1;
|
|
return this.sampleRate / this.inputSampleRate;
|
|
}
|
|
resample(input) {
|
|
const bytesPerFrame = this.bytes * this.channels;
|
|
const inputFrames = Math.floor(input.length / bytesPerFrame);
|
|
const outputFrames = Math.floor(
|
|
inputFrames * this.inputSampleRate / this.sampleRate
|
|
);
|
|
const output = Buffer.alloc(outputFrames * bytesPerFrame);
|
|
for (let outFrame = 0; outFrame < outputFrames; outFrame++) {
|
|
const inPos = outFrame * this.sampleRate / this.inputSampleRate;
|
|
const inFrame = Math.floor(inPos);
|
|
if (inFrame >= inputFrames - 1 || (inFrame + 1) * bytesPerFrame + (this.channels - 1) * this.bytes > input.length) {
|
|
break;
|
|
}
|
|
const fraction = inPos - inFrame;
|
|
for (let channel = 0; channel < this.channels; channel++) {
|
|
const pos1 = inFrame * bytesPerFrame + channel * this.bytes;
|
|
const pos2 = (inFrame + 1) * bytesPerFrame + channel * this.bytes;
|
|
if (pos1 + this.bytes > input.length || pos2 + this.bytes > input.length) {
|
|
continue;
|
|
}
|
|
const sample1 = this._readInt(input, pos1);
|
|
const sample2 = this._readInt(input, pos2);
|
|
const interpolated = sample1 + fraction * (sample2 - sample1);
|
|
const clamped = this.clamp(Math.round(interpolated));
|
|
const outPos = outFrame * bytesPerFrame + channel * this.bytes;
|
|
this._writeInt(output, clamped, outPos);
|
|
}
|
|
}
|
|
return output;
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
if (this.disabled || this.sampleRate === this.inputSampleRate) {
|
|
this.push(chunk);
|
|
callback();
|
|
return;
|
|
}
|
|
this.buffer = Buffer.concat([this.buffer, chunk]);
|
|
const bytesPerFrame = this.bytes * this.channels;
|
|
const minFramesNeeded = Math.ceil(
|
|
bytesPerFrame * (this.inputSampleRate / this.sampleRate)
|
|
);
|
|
const completeFrames = Math.floor(this.buffer.length / bytesPerFrame) - 1;
|
|
if (completeFrames >= minFramesNeeded) {
|
|
const processSize = completeFrames * bytesPerFrame;
|
|
const toProcess = this.buffer.slice(0, processSize);
|
|
this.buffer = this.buffer.slice(processSize);
|
|
const resampled = this.resample(toProcess);
|
|
this.push(resampled);
|
|
}
|
|
callback();
|
|
}
|
|
_flush(callback) {
|
|
if (this.disabled) {
|
|
callback();
|
|
return;
|
|
}
|
|
if (this.buffer.length > 0) {
|
|
const resampled = this.resample(this.buffer);
|
|
this.push(resampled);
|
|
}
|
|
callback();
|
|
}
|
|
setSampleRate(rate) {
|
|
if (rate === this.sampleRate) return;
|
|
if (rate < 1) {
|
|
throw new RangeError("Sample rate must be greater than 0");
|
|
}
|
|
super.setSampleRate(rate);
|
|
this.onUpdate();
|
|
}
|
|
};
|
|
__name(_PCMResampler, "PCMResampler");
|
|
var PCMResampler = _PCMResampler;
|
|
|
|
// src/audio/VolumeTransformer.ts
|
|
var _VolumeTransformer = class _VolumeTransformer extends PCMTransformer {
|
|
constructor(options) {
|
|
super(options);
|
|
__publicField(this, "_volume", 1);
|
|
if (typeof options?.volume === "number") {
|
|
this.setVolume(options.volume);
|
|
}
|
|
}
|
|
get volumeApprox() {
|
|
return this._volume * 100;
|
|
}
|
|
get volume() {
|
|
return Math.floor(this.volumeApprox);
|
|
}
|
|
set volume(volume) {
|
|
this.setVolume(volume);
|
|
}
|
|
setVolume(volume) {
|
|
if (typeof volume !== "number" || isNaN(volume))
|
|
throw new Error(
|
|
`Expected volume amount to be a number, received ${typeof volume}!`
|
|
);
|
|
if (volume < 0) volume = 0;
|
|
if (!isFinite(volume)) volume = 100;
|
|
this._volume = volume / 100;
|
|
this.onUpdate?.();
|
|
return true;
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
if (this.disabled || this._volume === 1) {
|
|
this.push(chunk);
|
|
return callback();
|
|
}
|
|
const len = Math.floor(chunk.length / 2) * 2;
|
|
const { bytes } = this;
|
|
for (let i = 0; i < len; i += bytes) {
|
|
const int = this._readInt(chunk, i);
|
|
const amp = this.clamp(int * this._volume);
|
|
this._writeInt(chunk, amp, i);
|
|
}
|
|
this.push(chunk);
|
|
return callback();
|
|
}
|
|
toString() {
|
|
return `${this.volume}%`;
|
|
}
|
|
};
|
|
__name(_VolumeTransformer, "VolumeTransformer");
|
|
var VolumeTransformer = _VolumeTransformer;
|
|
|
|
// src/audio/CompressorTransformer.ts
|
|
var _CompressorTransformer = class _CompressorTransformer extends PCMTransformer {
|
|
constructor(options = {}) {
|
|
super(options);
|
|
__publicField(this, "threshold");
|
|
__publicField(this, "ratio");
|
|
__publicField(this, "attack");
|
|
__publicField(this, "release");
|
|
__publicField(this, "makeupGain");
|
|
__publicField(this, "kneeWidth");
|
|
__publicField(this, "envelope", 0);
|
|
__publicField(this, "gainReduction", 1);
|
|
__publicField(this, "previousGainReduction", 1);
|
|
this.threshold = options.threshold ?? -20;
|
|
this.ratio = options.ratio ?? 4;
|
|
this.attack = options.attack ?? 20;
|
|
this.release = options.release ?? 100;
|
|
this.makeupGain = options.makeupGain ?? 0;
|
|
this.kneeWidth = options.kneeWidth ?? 6;
|
|
this.attack = Math.exp(-1 / (this.sampleRate * this.attack / 1e3));
|
|
this.release = Math.exp(-1 / (this.sampleRate * this.release / 1e3));
|
|
}
|
|
linearToDb(linear) {
|
|
const val = 20 * Math.log10(Math.max(linear, 1e-6));
|
|
return val;
|
|
}
|
|
dbToLinear(db) {
|
|
const val = Math.pow(10, db / 20);
|
|
return val;
|
|
}
|
|
setThreshold(db) {
|
|
this.threshold = Math.max(-100, Math.min(0, db));
|
|
this.onUpdate();
|
|
}
|
|
setRatio(ratio) {
|
|
this.ratio = Math.max(1, ratio);
|
|
this.onUpdate();
|
|
}
|
|
setAttack(ms) {
|
|
this.attack = Math.exp(-1 / (this.sampleRate * Math.max(0.1, ms) / 1e3));
|
|
this.onUpdate();
|
|
}
|
|
setRelease(ms) {
|
|
this.release = Math.exp(
|
|
-1 / (this.sampleRate * Math.max(0.1, ms) / 1e3)
|
|
);
|
|
this.onUpdate();
|
|
}
|
|
setMakeupGain(db) {
|
|
this.makeupGain = Math.max(-20, Math.min(20, db));
|
|
this.onUpdate();
|
|
}
|
|
setKneeWidth(db) {
|
|
this.kneeWidth = Math.max(0, Math.min(20, db));
|
|
this.onUpdate();
|
|
}
|
|
setCompressor(options) {
|
|
if (typeof options.threshold === "number") {
|
|
this.setThreshold(options.threshold);
|
|
}
|
|
if (typeof options.ratio === "number") {
|
|
this.setRatio(options.ratio);
|
|
}
|
|
if (typeof options.attack === "number") {
|
|
this.setAttack(options.attack);
|
|
}
|
|
if (typeof options.release === "number") {
|
|
this.setRelease(options.release);
|
|
}
|
|
if (typeof options.makeupGain === "number") {
|
|
this.setMakeupGain(options.makeupGain);
|
|
}
|
|
if (typeof options.kneeWidth === "number") {
|
|
this.setKneeWidth(options.kneeWidth);
|
|
}
|
|
this.onUpdate();
|
|
return this.getParameters();
|
|
}
|
|
getParameters() {
|
|
return {
|
|
threshold: this.threshold,
|
|
ratio: this.ratio,
|
|
attack: this.attack,
|
|
release: this.release,
|
|
makeupGain: this.makeupGain,
|
|
kneeWidth: this.kneeWidth
|
|
};
|
|
}
|
|
computeGainReduction(inputLevel) {
|
|
const inputDb = this.linearToDb(inputLevel);
|
|
let gainReductionDb = 0;
|
|
if (2 * (inputDb - this.threshold) < -this.kneeWidth) {
|
|
gainReductionDb = 0;
|
|
} else if (2 * Math.abs(inputDb - this.threshold) <= this.kneeWidth) {
|
|
const x = inputDb - this.threshold + this.kneeWidth / 2;
|
|
gainReductionDb = (1 / this.ratio - 1) * Math.pow(x, 2) / (2 * this.kneeWidth);
|
|
} else {
|
|
gainReductionDb = (inputDb - this.threshold) * (1 - 1 / this.ratio);
|
|
}
|
|
return this.dbToLinear(-gainReductionDb + this.makeupGain);
|
|
}
|
|
processSample(input) {
|
|
if (this.disabled) return input;
|
|
const inputFloat = input / this.extremum;
|
|
const inputLevel = Math.abs(inputFloat);
|
|
const coeff = inputLevel > this.envelope ? this.attack : this.release;
|
|
this.envelope = coeff * this.envelope + (1 - coeff) * inputLevel;
|
|
const targetGainReduction = this.computeGainReduction(this.envelope);
|
|
this.gainReduction = Math.min(
|
|
this.previousGainReduction * this.attack + targetGainReduction * (1 - this.attack),
|
|
targetGainReduction
|
|
);
|
|
this.previousGainReduction = this.gainReduction;
|
|
const outputFloat = inputFloat * this.gainReduction;
|
|
return this.clamp(Math.floor(outputFloat * this.extremum));
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
if (this.disabled) {
|
|
callback(null, chunk);
|
|
return;
|
|
}
|
|
const output = Buffer.alloc(chunk.length);
|
|
for (let i = 0; i < chunk.length; i += this.bytes) {
|
|
const sample = this._readInt(chunk, i);
|
|
const processed = this.processSample(sample);
|
|
this._writeInt(output, processed, i);
|
|
}
|
|
callback(null, output);
|
|
}
|
|
};
|
|
__name(_CompressorTransformer, "CompressorTransformer");
|
|
var CompressorTransformer = _CompressorTransformer;
|
|
|
|
// src/audio/PCMSeekerTransformer.ts
|
|
var import_events = require("events");
|
|
var _PCMSeekerTransformer = class _PCMSeekerTransformer extends PCMTransformer {
|
|
constructor(options = {
|
|
channels: 2,
|
|
totalDuration: 0
|
|
}) {
|
|
super(options);
|
|
__publicField(this, "totalDuration");
|
|
__publicField(this, "channels");
|
|
__publicField(this, "bytesPerFrame");
|
|
__publicField(this, "currentPosition", 0);
|
|
__publicField(this, "seekTarget", null);
|
|
__publicField(this, "buffer", Buffer.alloc(0));
|
|
__publicField(this, "events", new import_events.EventEmitter());
|
|
if (options.totalDuration == null || options.totalDuration < 0) {
|
|
throw new Error("totalDuration must be a positive number");
|
|
}
|
|
if (!options.channels || options.channels <= 0) {
|
|
throw new Error("channels must be a positive number");
|
|
}
|
|
this.totalDuration = options.totalDuration;
|
|
this.channels = options.channels;
|
|
if (typeof options.seekTarget === "number" && options.seekTarget > 0) {
|
|
this.seekTarget = options.seekTarget;
|
|
}
|
|
this.updateDependentValues();
|
|
}
|
|
getParameters() {
|
|
return {
|
|
currentPosition: this.currentPosition,
|
|
seekTarget: this.seekTarget,
|
|
totalDuration: this.totalDuration
|
|
};
|
|
}
|
|
updateDependentValues() {
|
|
this.bytesPerFrame = this.bytes * this.channels;
|
|
if (this.currentPosition > 0) {
|
|
const currentMs = this.currentPosition / (this.sampleRate / 1e3);
|
|
this.currentPosition = Math.floor(currentMs / 1e3 * this.sampleRate);
|
|
}
|
|
if (this.seekTarget !== null) {
|
|
const seekMs = this.seekTarget / (this.sampleRate / 1e3);
|
|
this.seekTarget = Math.floor(seekMs / 1e3 * this.sampleRate);
|
|
}
|
|
}
|
|
/**
|
|
* Calculate byte position from sample position
|
|
* @param samplePosition Position in samples
|
|
* @returns Position in bytes
|
|
*/
|
|
sampleToBytePosition(samplePosition) {
|
|
return samplePosition * this.bytesPerFrame;
|
|
}
|
|
setTotalDuration(duration) {
|
|
if (duration <= 0) {
|
|
throw new Error("totalDuration must be a positive number");
|
|
}
|
|
this.totalDuration = duration;
|
|
this.updateDependentValues();
|
|
this.onUpdate();
|
|
}
|
|
setSampleRate(rate) {
|
|
super.setSampleRate(rate);
|
|
this.updateDependentValues();
|
|
this.onUpdate();
|
|
}
|
|
/**
|
|
* Seek to a specific position in milliseconds
|
|
* @param ms Position in milliseconds (negative values seek from end)
|
|
* @returns Actual position in milliseconds after seeking
|
|
*/
|
|
seek(ms) {
|
|
if (this.totalDuration === 0) return 0;
|
|
if (ms < 0) {
|
|
ms = Math.max(0, this.totalDuration + ms);
|
|
}
|
|
ms = Math.max(0, Math.min(this.totalDuration, ms));
|
|
const targetSample = Math.floor(ms / 1e3 * this.sampleRate);
|
|
if (targetSample < this.currentPosition) {
|
|
this.buffer = Buffer.alloc(0);
|
|
const bytePosition = this.sampleToBytePosition(targetSample);
|
|
this.events.emit("seek", {
|
|
position: ms,
|
|
sample: targetSample,
|
|
bytePosition
|
|
});
|
|
}
|
|
this.seekTarget = targetSample;
|
|
return targetSample / this.sampleRate * 1e3;
|
|
}
|
|
getPosition() {
|
|
return this.currentPosition / this.sampleRate * 1e3;
|
|
}
|
|
handleSeek(chunk) {
|
|
if (this.seekTarget === null) return chunk;
|
|
const chunkStartSample = this.currentPosition;
|
|
const chunkSamples = Math.floor(chunk.length / this.bytesPerFrame);
|
|
const chunkEndSample = chunkStartSample + chunkSamples;
|
|
if (this.seekTarget >= chunkEndSample) {
|
|
this.currentPosition += chunkSamples;
|
|
return Buffer.alloc(0);
|
|
}
|
|
if (this.seekTarget >= chunkStartSample) {
|
|
const offsetSamples = this.seekTarget - chunkStartSample;
|
|
const offsetBytes = offsetSamples * this.bytesPerFrame;
|
|
this.currentPosition = this.seekTarget;
|
|
this.seekTarget = null;
|
|
return chunk.subarray(offsetBytes);
|
|
}
|
|
this.currentPosition = this.seekTarget;
|
|
this.seekTarget = null;
|
|
return chunk;
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
try {
|
|
if (this.disabled || this.totalDuration === 0) {
|
|
callback(null, chunk);
|
|
return;
|
|
}
|
|
const combinedBuffer = Buffer.concat([this.buffer, chunk]);
|
|
const frameCount = Math.floor(combinedBuffer.length / this.bytesPerFrame);
|
|
const processableBytes = frameCount * this.bytesPerFrame;
|
|
this.buffer = combinedBuffer.subarray(processableBytes);
|
|
let processBuffer = combinedBuffer.subarray(0, processableBytes);
|
|
if (this.seekTarget !== null) {
|
|
processBuffer = this.handleSeek(processBuffer);
|
|
} else {
|
|
this.currentPosition += frameCount;
|
|
}
|
|
callback(null, processBuffer);
|
|
} catch (error) {
|
|
callback(error);
|
|
}
|
|
}
|
|
_flush(callback) {
|
|
if (this.buffer.length >= this.bytesPerFrame) {
|
|
const frameCount = Math.floor(this.buffer.length / this.bytesPerFrame);
|
|
const processableBytes = frameCount * this.bytesPerFrame;
|
|
callback(null, this.buffer.subarray(0, processableBytes));
|
|
}
|
|
callback();
|
|
}
|
|
};
|
|
__name(_PCMSeekerTransformer, "PCMSeekerTransformer");
|
|
var PCMSeekerTransformer = _PCMSeekerTransformer;
|
|
|
|
// src/audio/ReverbTransformer.ts
|
|
var _ReverbTransformer = class _ReverbTransformer extends PCMTransformer {
|
|
constructor(options = {}) {
|
|
super(options);
|
|
__publicField(this, "roomSize");
|
|
__publicField(this, "damping");
|
|
__publicField(this, "wetLevel");
|
|
__publicField(this, "dryLevel");
|
|
__publicField(this, "delayLines");
|
|
__publicField(this, "delayLineLength");
|
|
__publicField(this, "delayIndices");
|
|
__publicField(this, "numDelayLines", 8);
|
|
__publicField(this, "feedback", 0.84);
|
|
this.roomSize = options.roomSize ?? 0.5;
|
|
this.damping = options.damping ?? 0.5;
|
|
this.wetLevel = options.wetLevel ?? 0.3;
|
|
this.dryLevel = options.dryLevel ?? 0.7;
|
|
this.delayLineLength = Math.floor(this.sampleRate * 0.05);
|
|
this.delayLines = Array.from(
|
|
{ length: this.numDelayLines },
|
|
() => new Float32Array(this.delayLineLength)
|
|
);
|
|
this.delayIndices = Array(this.numDelayLines).fill(0);
|
|
}
|
|
setRoomSize(size) {
|
|
this.roomSize = Math.max(0, Math.min(1, size));
|
|
this.onUpdate();
|
|
}
|
|
setDamping(damping) {
|
|
this.damping = Math.max(0, Math.min(1, damping));
|
|
this.onUpdate();
|
|
}
|
|
setWetLevel(level) {
|
|
this.wetLevel = Math.max(0, Math.min(1, level));
|
|
this.onUpdate();
|
|
}
|
|
setDryLevel(level) {
|
|
this.dryLevel = Math.max(0, Math.min(1, level));
|
|
this.onUpdate();
|
|
}
|
|
setReverb(options) {
|
|
if (typeof options.roomSize === "number") {
|
|
this.setRoomSize(options.roomSize);
|
|
}
|
|
if (typeof options.damping === "number") {
|
|
this.setDamping(options.damping);
|
|
}
|
|
if (typeof options.wetLevel === "number") {
|
|
this.setWetLevel(options.wetLevel);
|
|
}
|
|
if (typeof options.dryLevel === "number") {
|
|
this.setDryLevel(options.dryLevel);
|
|
}
|
|
this.onUpdate();
|
|
return this.getParameters();
|
|
}
|
|
getParameters() {
|
|
return {
|
|
roomSize: this.roomSize,
|
|
damping: this.damping,
|
|
wetLevel: this.wetLevel,
|
|
dryLevel: this.dryLevel
|
|
};
|
|
}
|
|
processSample(input) {
|
|
if (this.disabled) return input;
|
|
const inputFloat = input / this.extremum;
|
|
let wet = 0;
|
|
for (let i = 0; i < this.numDelayLines; i++) {
|
|
const delayLine = this.delayLines[i];
|
|
const delayIndex = this.delayIndices[i];
|
|
const delayed = delayLine[delayIndex];
|
|
const processed = delayed * this.roomSize * (1 - this.damping);
|
|
delayLine[delayIndex] = inputFloat + processed * this.feedback;
|
|
this.delayIndices[i] = (delayIndex + 1) % this.delayLineLength;
|
|
wet += processed;
|
|
}
|
|
const output = inputFloat * this.dryLevel + wet * this.wetLevel / this.numDelayLines;
|
|
return this.clamp(Math.floor(output * this.extremum));
|
|
}
|
|
_transform(chunk, encoding, callback) {
|
|
if (this.disabled) {
|
|
callback(null, chunk);
|
|
return;
|
|
}
|
|
const output = Buffer.alloc(chunk.length);
|
|
for (let i = 0; i < chunk.length; i += this.bytes) {
|
|
const sample = this._readInt(chunk, i);
|
|
const processed = this.processSample(sample);
|
|
this._writeInt(output, processed, i);
|
|
}
|
|
callback(null, output);
|
|
}
|
|
};
|
|
__name(_ReverbTransformer, "ReverbTransformer");
|
|
var ReverbTransformer = _ReverbTransformer;
|
|
|
|
// src/FiltersChainBuilder.ts
|
|
var import_stream2 = require("stream");
|
|
var _FiltersChain = class _FiltersChain {
|
|
constructor(presets = {}) {
|
|
this.presets = presets;
|
|
__publicField(this, "equalizer", null);
|
|
__publicField(this, "filters", null);
|
|
__publicField(this, "biquad", null);
|
|
__publicField(this, "volume", null);
|
|
__publicField(this, "resampler", null);
|
|
__publicField(this, "compressor", null);
|
|
__publicField(this, "seeker", null);
|
|
__publicField(this, "reverb", null);
|
|
__publicField(this, "destination", null);
|
|
__publicField(this, "source", null);
|
|
__publicField(this, "onUpdate", /* @__PURE__ */ __name(() => null, "onUpdate"));
|
|
__publicField(this, "onError", /* @__PURE__ */ __name(() => null, "onError"));
|
|
}
|
|
create(src, presets = this.presets) {
|
|
this.destroy();
|
|
this.source = src;
|
|
const resampler = !presets.resampler?.disabled ? new PCMResampler(presets.resampler) : null;
|
|
const equalizerStream = !presets.equalizer?.disabled ? new EqualizerStream(presets.equalizer) : null;
|
|
const dspStream = !presets.dsp?.disabled ? new AudioFilter(presets.dsp) : null;
|
|
const biquadStream = !presets.biquad?.disabled ? new BiquadStream(presets.biquad) : null;
|
|
const volumeTransformer = !presets.volume?.disabled ? new VolumeTransformer(presets.volume) : null;
|
|
const compressor = !presets.compressor?.disabled ? new CompressorTransformer(presets.compressor) : null;
|
|
const seeker = !presets.seeker?.disabled ? new PCMSeekerTransformer(presets.seeker) : null;
|
|
const reverb = !presets.reverb?.disabled ? new ReverbTransformer(presets.reverb) : null;
|
|
this.resampler = resampler;
|
|
this.equalizer = equalizerStream;
|
|
this.filters = dspStream;
|
|
this.biquad = biquadStream;
|
|
this.volume = volumeTransformer;
|
|
this.compressor = compressor;
|
|
this.seeker = seeker;
|
|
this.reverb = reverb;
|
|
if (resampler) resampler.onUpdate = this.onUpdate;
|
|
if (equalizerStream) equalizerStream.onUpdate = this.onUpdate;
|
|
if (dspStream) dspStream.onUpdate = this.onUpdate;
|
|
if (biquadStream) biquadStream.onUpdate = this.onUpdate;
|
|
if (volumeTransformer) volumeTransformer.onUpdate = this.onUpdate;
|
|
if (compressor) compressor.onUpdate = this.onUpdate;
|
|
if (seeker) seeker.onUpdate = this.onUpdate;
|
|
if (reverb) reverb.onUpdate = this.onUpdate;
|
|
const chains = [
|
|
src,
|
|
resampler,
|
|
equalizerStream,
|
|
reverb,
|
|
dspStream,
|
|
biquadStream,
|
|
compressor,
|
|
volumeTransformer,
|
|
seeker
|
|
].filter(Boolean);
|
|
if (!chains.length) return src;
|
|
this.destination = (0, import_stream2.pipeline)(...chains, (err) => {
|
|
if (err) {
|
|
this.destroy();
|
|
if (!err.message.includes("ERR_STREAM_PREMATURE_CLOSE"))
|
|
this.onError(err);
|
|
}
|
|
});
|
|
this.destination.once("close", this.destroy.bind(this));
|
|
return this.destination;
|
|
}
|
|
destroy() {
|
|
this.resampler?.destroy();
|
|
this.equalizer?.destroy();
|
|
this.biquad?.destroy();
|
|
this.filters?.destroy();
|
|
this.volume?.destroy();
|
|
this.compressor?.destroy();
|
|
this.seeker?.destroy();
|
|
this.reverb?.destroy();
|
|
this.destination?.destroy();
|
|
this.source?.destroy();
|
|
this.resampler?.removeAllListeners();
|
|
this.equalizer?.removeAllListeners();
|
|
this.biquad?.removeAllListeners();
|
|
this.filters?.removeAllListeners();
|
|
this.volume?.removeAllListeners();
|
|
this.compressor?.removeAllListeners();
|
|
this.seeker?.removeAllListeners();
|
|
this.reverb?.removeAllListeners();
|
|
this.destination?.removeAllListeners();
|
|
this.source?.removeAllListeners();
|
|
this.resampler = null;
|
|
this.equalizer = null;
|
|
this.biquad = null;
|
|
this.filters = null;
|
|
this.volume = null;
|
|
this.compressor = null;
|
|
this.seeker = null;
|
|
this.reverb = null;
|
|
this.destination = null;
|
|
this.source = null;
|
|
}
|
|
};
|
|
__name(_FiltersChain, "FiltersChain");
|
|
var FiltersChain = _FiltersChain;
|
|
|
|
// src/version.ts
|
|
var version = (
|
|
/* @__MACRO__ getVersion */
|
|
"7.2.0"
|
|
);
|
|
// Annotate the CommonJS export names for ESM import in node:
|
|
0 && (module.exports = {
|
|
AF_NIGHTCORE_RATE,
|
|
AF_VAPORWAVE_RATE,
|
|
AudioFilter,
|
|
AudioFilters,
|
|
BASS_EQ_BANDS,
|
|
BiquadFilter,
|
|
BiquadStream,
|
|
ChannelProcessor,
|
|
Coefficients,
|
|
CompressorTransformer,
|
|
Equalizer,
|
|
EqualizerCoefficients,
|
|
EqualizerConfiguration,
|
|
EqualizerStream,
|
|
FilterType,
|
|
FiltersChain,
|
|
Frequency,
|
|
MonoStereoTransformer,
|
|
PCMAudioTransformer,
|
|
PCMResampler,
|
|
PCMSeekerTransformer,
|
|
PCMTransformer,
|
|
Q_BUTTERWORTH,
|
|
ReverbTransformer,
|
|
VolumeTransformer,
|
|
version
|
|
});
|
|
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9iaXF1YWQvQ29lZmZpY2llbnRzLnRzIiwgIi4uL3NyYy9iaXF1YWQvQmlxdWFkLnRzIiwgIi4uL3NyYy91dGlscy9GcmVxdWVuY3kudHMiLCAiLi4vc3JjL3V0aWxzL1BDTVRyYW5zZm9ybWVyLnRzIiwgIi4uL3NyYy9iaXF1YWQvQmlxdWFkU3RyZWFtLnRzIiwgIi4uL3NyYy9lcXVhbGl6ZXIvQ2hhbm5lbFByb2Nlc3Nvci50cyIsICIuLi9zcmMvZXF1YWxpemVyL0NvZWZmaWNpZW50cy50cyIsICIuLi9zcmMvZXF1YWxpemVyL0VxdWFsaXplckNvbmZpZ3VyYXRpb24udHMiLCAiLi4vc3JjL2VxdWFsaXplci9FcXVhbGl6ZXIudHMiLCAiLi4vc3JjL2VxdWFsaXplci9FcXVhbGl6ZXJTdHJlYW0udHMiLCAiLi4vc3JjL2F1ZGlvL01vbm9TdGVyZW9UcmFuc2Zvcm1lci50cyIsICIuLi9zcmMvYXVkaW8vdHJhbnNmb3JtZXJzL2luZGV4LnRzIiwgIi4uL3NyYy9hdWRpby90cmFuc2Zvcm1lcnMvYmlxdWFkLnRzIiwgIi4uL3NyYy9hdWRpby90cmFuc2Zvcm1lcnMvZHNwLnRzIiwgIi4uL3NyYy9hdWRpby90cmFuc2Zvcm1lcnMvZXF1YWxpemVyLnRzIiwgIi4uL3NyYy9hdWRpby9BdWRpb0ZpbHRlci50cyIsICIuLi9zcmMvYXVkaW8vUENNUmVzYW1wbGVyLnRzIiwgIi4uL3NyYy9hdWRpby9Wb2x1bWVUcmFuc2Zvcm1lci50cyIsICIuLi9zcmMvYXVkaW8vQ29tcHJlc3NvclRyYW5zZm9ybWVyLnRzIiwgIi4uL3NyYy9hdWRpby9QQ01TZWVrZXJUcmFuc2Zvcm1lci50cyIsICIuLi9zcmMvYXVkaW8vUmV2ZXJiVHJhbnNmb3JtZXIudHMiLCAiLi4vc3JjL0ZpbHRlcnNDaGFpbkJ1aWxkZXIudHMiLCAiLi4vc3JjL3ZlcnNpb24udHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImV4cG9ydCAqIGZyb20gJy4vYmlxdWFkJztcbmV4cG9ydCAqIGZyb20gJy4vZXF1YWxpemVyJztcbmV4cG9ydCAqIGZyb20gJy4vdXRpbHMnO1xuZXhwb3J0ICogZnJvbSAnLi9hdWRpbyc7XG5leHBvcnQgKiBmcm9tICcuL0ZpbHRlcnNDaGFpbkJ1aWxkZXInO1xuZXhwb3J0IHsgdmVyc2lvbiB9IGZyb20gJy4vdmVyc2lvbic7IiwgImV4cG9ydCBjb25zdCBGaWx0ZXJUeXBlID0ge1xuICBTaW5nbGVQb2xlTG93UGFzc0FwcHJveDogMCxcbiAgU2luZ2xlUG9sZUxvd1Bhc3M6IDEsXG4gIExvd1Bhc3M6IDIsXG4gIEhpZ2hQYXNzOiAzLFxuICBCYW5kUGFzczogNCxcbiAgTm90Y2g6IDUsXG4gIEFsbFBhc3M6IDYsXG4gIExvd1NoZWxmOiA3LFxuICBIaWdoU2hlbGY6IDgsXG4gIFBlYWtpbmdFUTogOVxufSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgQmlxdWFkRmlsdGVycyA9XG5rZXlvZiB0eXBlb2YgRmlsdGVyVHlwZSB8XG4odHlwZW9mIEZpbHRlclR5cGUpW2tleW9mIHR5cGVvZiBGaWx0ZXJUeXBlXTtcblxuaW50ZXJmYWNlIENvZWZmaWNpZW50c0luaXQge1xuICBhMTogbnVtYmVyO1xuICBhMjogbnVtYmVyO1xuICBiMDogbnVtYmVyO1xuICBiMTogbnVtYmVyO1xuICBiMjogbnVtYmVyO1xufVxuXG5leHBvcnQgY29uc3QgUV9CVVRURVJXT1JUSCA9IE1hdGguU1FSVDFfMjtcblxuZXhwb3J0IGNsYXNzIENvZWZmaWNpZW50cyB7XG4gIC8vIERlbm9taW5hdG9yIGNvZWZmaWNpZW50c1xuICBwdWJsaWMgYTEgPSAwO1xuICBwdWJsaWMgYTIgPSAwO1xuXG4gIC8vIE5vbWluYXRvciBjb2VmZmljaWVudHNcbiAgcHVibGljIGIwID0gMDtcbiAgcHVibGljIGIxID0gMDtcbiAgcHVibGljIGIyID0gMDtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoZGF0YT86IENvZWZmaWNpZW50c0luaXQpIHtcbiAgICBpZiAoZGF0YSkge1xuICAgICAgdGhpcy5hMSA9IGRhdGEuYTE7XG4gICAgICB0aGlzLmEyID0gZGF0YS5hMjtcbiAgICAgIHRoaXMuYjAgPSBkYXRhLmIwO1xuICAgICAgdGhpcy5iMSA9IGRhdGEuYjE7XG4gICAgICB0aGlzLmIyID0gZGF0YS5iMjtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgc3RhdGljIGZyb20oXG4gIGZpbHRlcjogQmlxdWFkRmlsdGVycyxcbiAgc2FtcGxpbmdGcmVxOiBudW1iZXIsXG4gIGN1dG9mZkZyZXE6IG51bWJlcixcbiAgUTogbnVtYmVyLFxuICBkYkdhaW4gPSAtMTApXG4gIHtcbiAgICBpZiAoMi4wICogY3V0b2ZmRnJlcSA+IHNhbXBsaW5nRnJlcSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBDdXRvZmYgZnJlcXVlbmN5IGlzIHRvbyBiaWchYCk7XG4gICAgfVxuXG4gICAgaWYgKFEgPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFEgbWF5IG5vdCBiZSBuZWdhdGl2ZWApO1xuICAgIH1cblxuICAgIGNvbnN0IG9tZWdhID0gMi4wICogTWF0aC5QSSAqIGN1dG9mZkZyZXEgLyBzYW1wbGluZ0ZyZXE7XG5cbiAgICBjb25zdCBicWYgPSB0eXBlb2YgZmlsdGVyID09PSAnc3RyaW5nJyA/IEZpbHRlclR5cGVbZmlsdGVyXSA6IGZpbHRlcjtcblxuICAgIHN3aXRjaCAoYnFmKSB7XG4gICAgICBjYXNlIEZpbHRlclR5cGUuU2luZ2xlUG9sZUxvd1Bhc3NBcHByb3g6e1xuICAgICAgICAgIGNvbnN0IGFscGhhID0gb21lZ2EgLyAob21lZ2EgKyAxLjApO1xuXG4gICAgICAgICAgcmV0dXJuIG5ldyBDb2VmZmljaWVudHMoe1xuICAgICAgICAgICAgYTE6IGFscGhhIC0gMS4wLFxuICAgICAgICAgICAgYTI6IDAuMCxcbiAgICAgICAgICAgIGIwOiBhbHBoYSxcbiAgICAgICAgICAgIGIxOiAwLjAsXG4gICAgICAgICAgICBiMjogMC4wXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgRmlsdGVyVHlwZS5TaW5nbGVQb2xlTG93UGFzczp7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfdCA9IE1hdGgudGFuKG9tZWdhIC8gMi4wKTtcbiAgICAgICAgICBjb25zdCBhMCA9IDEuMCArIG9tZWdhX3Q7XG5cbiAgICAgICAgICByZXR1cm4gbmV3IENvZWZmaWNpZW50cyh7XG4gICAgICAgICAgICBhMTogKG9tZWdhX3QgLSAxLjApIC8gYTAsXG4gICAgICAgICAgICBhMjogMC4wLFxuICAgICAgICAgICAgYjA6IG9tZWdhX3QgLyBhMCxcbiAgICAgICAgICAgIGIxOiBvbWVnYV90IC8gYTAsXG4gICAgICAgICAgICBiMjogMC4wXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgRmlsdGVyVHlwZS5Mb3dQYXNzOntcbiAgICAgICAgICBjb25zdCBvbWVnYV9zID0gTWF0aC5zaW4ob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IG9tZWdhX2MgPSBNYXRoLmNvcyhvbWVnYSk7XG4gICAgICAgICAgY29uc3QgYWxwaGEgPSBvbWVnYV9zIC8gKDIuMCAqIFEpO1xuXG4gICAgICAgICAgY29uc3QgYjAgPSAoMS4wIC0gb21lZ2FfYykgKiAwLjU7XG4gICAgICAgICAgY29uc3QgYjEgPSAxLjAgLSBvbWVnYV9jO1xuICAgICAgICAgIGNvbnN0IGIyID0gKDEuMCAtIG9tZWdhX2MpICogMC41O1xuICAgICAgICAgIGNvbnN0IGEwID0gMS4wICsgYWxwaGE7XG4gICAgICAgICAgY29uc3QgYTEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBhMiA9IDEuMCAtIGFscGhhO1xuXG4gICAgICAgICAgY29uc3QgZGl2ID0gMS4wIC8gYTA7XG5cbiAgICAgICAgICByZXR1cm4gbmV3IENvZWZmaWNpZW50cyh7XG4gICAgICAgICAgICBhMTogYTEgKiBkaXYsXG4gICAgICAgICAgICBhMjogYTIgKiBkaXYsXG4gICAgICAgICAgICBiMDogYjAgKiBkaXYsXG4gICAgICAgICAgICBiMTogYjEgKiBkaXYsXG4gICAgICAgICAgICBiMjogYjIgKiBkaXZcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSBGaWx0ZXJUeXBlLkhpZ2hQYXNzOntcbiAgICAgICAgICBjb25zdCBvbWVnYV9zID0gTWF0aC5zaW4ob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IG9tZWdhX2MgPSBNYXRoLmNvcyhvbWVnYSk7XG4gICAgICAgICAgY29uc3QgYWxwaGEgPSBvbWVnYV9zIC8gKDIuMCAqIFEpO1xuXG4gICAgICAgICAgY29uc3QgYjAgPSAoMS4wICsgb21lZ2FfYykgKiAwLjU7XG4gICAgICAgICAgY29uc3QgYjEgPSAtKDEuMCArIG9tZWdhX2MpO1xuICAgICAgICAgIGNvbnN0IGIyID0gKDEuMCArIG9tZWdhX2MpICogMC41O1xuICAgICAgICAgIGNvbnN0IGEwID0gMS4wICsgYWxwaGE7XG4gICAgICAgICAgY29uc3QgYTEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBhMiA9IDEuMCAtIGFscGhhO1xuXG4gICAgICAgICAgY29uc3QgZGl2ID0gMS4wIC8gYTA7XG5cbiAgICAgICAgICByZXR1cm4gbmV3IENvZWZmaWNpZW50cyh7XG4gICAgICAgICAgICBhMTogYTEgKiBkaXYsXG4gICAgICAgICAgICBhMjogYTIgKiBkaXYsXG4gICAgICAgICAgICBiMDogYjAgKiBkaXYsXG4gICAgICAgICAgICBiMTogYjEgKiBkaXYsXG4gICAgICAgICAgICBiMjogYjIgKiBkaXZcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSBGaWx0ZXJUeXBlLk5vdGNoOntcbiAgICAgICAgICBjb25zdCBvbWVnYV9zID0gTWF0aC5zaW4ob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IG9tZWdhX2MgPSBNYXRoLmNvcyhvbWVnYSk7XG4gICAgICAgICAgY29uc3QgYWxwaGEgPSBvbWVnYV9zIC8gKDIuMCAqIFEpO1xuXG4gICAgICAgICAgY29uc3QgYjAgPSAxLjA7XG4gICAgICAgICAgY29uc3QgYjEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBiMiA9IDEuMDtcbiAgICAgICAgICBjb25zdCBhMCA9IDEuMCArIGFscGhhO1xuICAgICAgICAgIGNvbnN0IGExID0gLTIuMCAqIG9tZWdhX2M7XG4gICAgICAgICAgY29uc3QgYTIgPSAxLjAgLSBhbHBoYTtcblxuICAgICAgICAgIGNvbnN0IGRpdiA9IDEuMCAvIGEwO1xuXG4gICAgICAgICAgcmV0dXJuIG5ldyBDb2VmZmljaWVudHMoe1xuICAgICAgICAgICAgYTE6IGExICogZGl2LFxuICAgICAgICAgICAgYTI6IGEyICogZGl2LFxuICAgICAgICAgICAgYjA6IGIwICogZGl2LFxuICAgICAgICAgICAgYjE6IGIxICogZGl2LFxuICAgICAgICAgICAgYjI6IGIyICogZGl2XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgRmlsdGVyVHlwZS5CYW5kUGFzczp7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfcyA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBvbWVnYV9jID0gTWF0aC5jb3Mob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IGFscGhhID0gb21lZ2FfcyAvICgyLjAgKiBRKTtcblxuICAgICAgICAgIGNvbnN0IGIwID0gb21lZ2FfcyAvIDIuMDtcbiAgICAgICAgICBjb25zdCBiMSA9IDA7XG4gICAgICAgICAgY29uc3QgYjIgPSAtKG9tZWdhX3MgLyAyLjApO1xuICAgICAgICAgIGNvbnN0IGEwID0gMS4wICsgYWxwaGE7XG4gICAgICAgICAgY29uc3QgYTEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBhMiA9IDEuMCAtIGFscGhhO1xuXG4gICAgICAgICAgY29uc3QgZGl2ID0gMS4wIC8gYTA7XG5cbiAgICAgICAgICByZXR1cm4gbmV3IENvZWZmaWNpZW50cyh7XG4gICAgICAgICAgICBhMTogYTEgKiBkaXYsXG4gICAgICAgICAgICBhMjogYTIgKiBkaXYsXG4gICAgICAgICAgICBiMDogYjAgKiBkaXYsXG4gICAgICAgICAgICBiMTogYjEgKiBkaXYsXG4gICAgICAgICAgICBiMjogYjIgKiBkaXZcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSBGaWx0ZXJUeXBlLkFsbFBhc3M6e1xuICAgICAgICAgIGNvbnN0IG9tZWdhX3MgPSBNYXRoLnNpbihvbWVnYSk7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfYyA9IE1hdGguY29zKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBhbHBoYSA9IG9tZWdhX3MgLyAoMi4wICogUSk7XG5cbiAgICAgICAgICBjb25zdCBiMCA9IDEuMCAtIGFscGhhO1xuICAgICAgICAgIGNvbnN0IGIxID0gLTIuMCAqIG9tZWdhX2M7XG4gICAgICAgICAgY29uc3QgYjIgPSAxLjAgKyBhbHBoYTtcbiAgICAgICAgICBjb25zdCBhMCA9IDEuMCArIGFscGhhO1xuICAgICAgICAgIGNvbnN0IGExID0gLTIuMCAqIG9tZWdhX2M7XG4gICAgICAgICAgY29uc3QgYTIgPSAxLjAgLSBhbHBoYTtcblxuICAgICAgICAgIHJldHVybiBuZXcgQ29lZmZpY2llbnRzKHtcbiAgICAgICAgICAgIGExOiBhMSAvIGEwLFxuICAgICAgICAgICAgYTI6IGEyIC8gYTAsXG4gICAgICAgICAgICBiMDogYjAgLyBhMCxcbiAgICAgICAgICAgIGIxOiBiMSAvIGEwLFxuICAgICAgICAgICAgYjI6IGIyIC8gYTBcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSBGaWx0ZXJUeXBlLkxvd1NoZWxmOntcbiAgICAgICAgICBjb25zdCBhID0gTWF0aC5wb3coMTAuMCwgZGJHYWluIC8gNDAuMCk7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfcyA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBvbWVnYV9jID0gTWF0aC5jb3Mob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IGFscGhhID0gb21lZ2FfcyAvICgyLjAgKiBRKTtcblxuICAgICAgICAgIGNvbnN0IGIwID1cbiAgICAgICAgICBhICogKGEgKyAxLjAgLSAoYSAtIDEuMCkgKiBvbWVnYV9jICsgMi4wICogYWxwaGEgKiBNYXRoLnNxcnQoYSkpO1xuICAgICAgICAgIGNvbnN0IGIxID0gMi4wICogYSAqIChhIC0gMS4wIC0gKGEgKyAxLjApICogb21lZ2FfYyk7XG4gICAgICAgICAgY29uc3QgYjIgPVxuICAgICAgICAgIGEgKiAoYSArIDEuMCAtIChhIC0gMS4wKSAqIG9tZWdhX2MgLSAyLjAgKiBhbHBoYSAqIE1hdGguc3FydChhKSk7XG4gICAgICAgICAgY29uc3QgYTAgPSBhICsgMS4wICsgKGEgLSAxLjApICogb21lZ2FfYyArIDIuMCAqIGFscGhhICogTWF0aC5zcXJ0KGEpO1xuICAgICAgICAgIGNvbnN0IGExID0gLTIuMCAqIChhIC0gMS4wICsgKGEgKyAxLjApICogb21lZ2FfYyk7XG4gICAgICAgICAgY29uc3QgYTIgPSBhICsgMS4wICsgKGEgLSAxLjApICogb21lZ2FfYyAtIDIuMCAqIGFscGhhICogTWF0aC5zcXJ0KGEpO1xuXG4gICAgICAgICAgcmV0dXJuIG5ldyBDb2VmZmljaWVudHMoe1xuICAgICAgICAgICAgYTE6IGExIC8gYTAsXG4gICAgICAgICAgICBhMjogYTIgLyBhMCxcbiAgICAgICAgICAgIGIwOiBiMCAvIGEwLFxuICAgICAgICAgICAgYjE6IGIxIC8gYTAsXG4gICAgICAgICAgICBiMjogYjIgLyBhMFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICBjYXNlIEZpbHRlclR5cGUuSGlnaFNoZWxmOntcbiAgICAgICAgICBjb25zdCBhID0gTWF0aC5wb3coMTAuMCwgZGJHYWluIC8gNDAuMCk7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfcyA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBvbWVnYV9jID0gTWF0aC5jb3Mob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IGFscGhhID0gb21lZ2FfcyAvICgyLjAgKiBRKTtcblxuICAgICAgICAgIGNvbnN0IGIwID1cbiAgICAgICAgICBhICogKGEgKyAxLjAgKyAoYSAtIDEuMCkgKiBvbWVnYV9jICsgMi4wICogYWxwaGEgKiBNYXRoLnNxcnQoYSkpO1xuICAgICAgICAgIGNvbnN0IGIxID0gLTIuMCAqIGEgKiAoYSAtIDEuMCArIChhICsgMS4wKSAqIG9tZWdhX2MpO1xuICAgICAgICAgIGNvbnN0IGIyID1cbiAgICAgICAgICBhICogKGEgKyAxLjAgKyAoYSAtIDEuMCkgKiBvbWVnYV9jIC0gMi4wICogYWxwaGEgKiBNYXRoLnNxcnQoYSkpO1xuICAgICAgICAgIGNvbnN0IGEwID0gYSArIDEuMCAtIChhIC0gMS4wKSAqIG9tZWdhX2MgKyAyLjAgKiBhbHBoYSAqIE1hdGguc3FydChhKTtcbiAgICAgICAgICBjb25zdCBhMSA9IDIuMCAqIChhIC0gMS4wIC0gKGEgKyAxLjApICogb21lZ2FfYyk7XG4gICAgICAgICAgY29uc3QgYTIgPSBhICsgMS4wIC0gKGEgLSAxLjApICogb21lZ2FfYyAtIDIuMCAqIGFscGhhICogTWF0aC5zcXJ0KGEpO1xuXG4gICAgICAgICAgcmV0dXJuIG5ldyBDb2VmZmljaWVudHMoe1xuICAgICAgICAgICAgYTE6IGExIC8gYTAsXG4gICAgICAgICAgICBhMjogYTIgLyBhMCxcbiAgICAgICAgICAgIGIwOiBiMCAvIGEwLFxuICAgICAgICAgICAgYjE6IGIxIC8gYTAsXG4gICAgICAgICAgICBiMjogYjIgLyBhMFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICBjYXNlIEZpbHRlclR5cGUuUGVha2luZ0VROntcbiAgICAgICAgICBjb25zdCBhID0gTWF0aC5wb3coMTAuMCwgZGJHYWluIC8gNDAuMCk7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfcyA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBvbWVnYV9jID0gTWF0aC5jb3Mob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IGFscGhhID0gb21lZ2FfcyAvICgyLjAgKiBRKTtcblxuICAgICAgICAgIGNvbnN0IGIwID0gMS4wICsgYWxwaGEgKiBhO1xuICAgICAgICAgIGNvbnN0IGIxID0gLTIuMCAqIG9tZWdhX2M7XG4gICAgICAgICAgY29uc3QgYjIgPSAxLjAgLSBhbHBoYSAqIGE7XG4gICAgICAgICAgY29uc3QgYTAgPSAxLjAgKyBhbHBoYSAvIGE7XG4gICAgICAgICAgY29uc3QgYTEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBhMiA9IDEuMCAtIGFscGhhIC8gYTtcblxuICAgICAgICAgIHJldHVybiBuZXcgQ29lZmZpY2llbnRzKHtcbiAgICAgICAgICAgIGExOiBhMSAvIGEwLFxuICAgICAgICAgICAgYTI6IGEyIC8gYTAsXG4gICAgICAgICAgICBiMDogYjAgLyBhMCxcbiAgICAgICAgICAgIGIxOiBiMSAvIGEwLFxuICAgICAgICAgICAgYjI6IGIyIC8gYTBcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBmaWx0ZXIgdHlwZSBcIiR7ZmlsdGVyfVwiYCk7XG4gICAgfVxuICB9XG59IiwgImltcG9ydCB7IEJpcXVhZEZpbHRlcnMsIENvZWZmaWNpZW50cyB9IGZyb20gJy4vQ29lZmZpY2llbnRzJztcblxuZXhwb3J0IGludGVyZmFjZSBCaXF1YWRTZXRGaWx0ZXJQcm9wcyB7XG4gIGYwOiBudW1iZXI7XG4gIGZzOiBudW1iZXI7XG4gIFE6IG51bWJlcjtcbiAgZ2Fpbj86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIEJpcXVhZEZpbHRlciB7XG4gIHB1YmxpYyB4MSA9IDAuMDtcbiAgcHVibGljIHgyID0gMC4wO1xuICBwdWJsaWMgeTEgPSAwLjA7XG4gIHB1YmxpYyB5MiA9IDAuMDtcbiAgcHVibGljIHMxID0gMC4wO1xuICBwdWJsaWMgczIgPSAwLjA7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyBjb2VmZmljaWVudHM6IENvZWZmaWNpZW50cykge31cblxuICBwdWJsaWMgc2V0RmlsdGVyKGZpbHRlcjogQmlxdWFkRmlsdGVycywgb3B0aW9uczogQmlxdWFkU2V0RmlsdGVyUHJvcHMpIHtcbiAgICBjb25zdCBjb2VmZmljaWVudHMgPSBDb2VmZmljaWVudHMuZnJvbShcbiAgICAgIGZpbHRlcixcbiAgICAgIG9wdGlvbnMuZnMsXG4gICAgICBvcHRpb25zLmYwLFxuICAgICAgb3B0aW9ucy5RLFxuICAgICAgb3B0aW9ucy5nYWluXG4gICAgKTtcblxuICAgIHRoaXMudXBkYXRlKGNvZWZmaWNpZW50cyk7XG4gIH1cblxuICBwdWJsaWMgdXBkYXRlKGNvZWZmaWNpZW50czogQ29lZmZpY2llbnRzKSB7XG4gICAgdGhpcy5jb2VmZmljaWVudHMgPSBjb2VmZmljaWVudHM7XG4gIH1cblxuICBwdWJsaWMgcmVwbGFjZShjb2VmZmljaWVudHM6IENvZWZmaWNpZW50cykge1xuICAgIHRoaXMuY29lZmZpY2llbnRzID0gY29lZmZpY2llbnRzO1xuICB9XG5cbiAgcHVibGljIHJlc2V0KCkge1xuICAgIHRoaXMueDEgPSAwLjA7XG4gICAgdGhpcy54MiA9IDAuMDtcbiAgICB0aGlzLnkxID0gMC4wO1xuICAgIHRoaXMueTIgPSAwLjA7XG4gICAgdGhpcy5zMSA9IDAuMDtcbiAgICB0aGlzLnMyID0gMC4wO1xuICB9XG5cbiAgcHVibGljIHJ1bihpbnB1dDogbnVtYmVyKSB7XG4gICAgY29uc3QgeyBhMSwgYTIsIGIwLCBiMSwgYjIgfSA9IHRoaXMuY29lZmZpY2llbnRzO1xuXG4gICAgY29uc3Qgb3V0ID1cbiAgICBiMCAqIGlucHV0ICsgYjEgKiB0aGlzLngxICsgYjIgKiB0aGlzLngyIC0gYTEgKiB0aGlzLnkxIC0gYTIgKiB0aGlzLnkyO1xuXG4gICAgdGhpcy54MiA9IHRoaXMueDE7XG4gICAgdGhpcy54MSA9IGlucHV0O1xuICAgIHRoaXMueTIgPSB0aGlzLnkxO1xuICAgIHRoaXMueTEgPSBvdXQ7XG5cbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgcHVibGljIHJ1blRyYW5zcG9zZWQoaW5wdXQ6IG51bWJlcikge1xuICAgIGNvbnN0IHsgYTEsIGEyLCBiMCwgYjEsIGIyIH0gPSB0aGlzLmNvZWZmaWNpZW50cztcblxuICAgIGNvbnN0IG91dCA9IHRoaXMuczEgKyBiMCAqIGlucHV0O1xuXG4gICAgdGhpcy5zMSA9IHRoaXMuczIgKyBiMSAqIGlucHV0IC0gYTEgKiBvdXQ7XG4gICAgdGhpcy5zMiA9IGIyICogaW5wdXQgLSBhMiAqIG91dDtcblxuICAgIHJldHVybiBvdXQ7XG4gIH1cbn0iLCAiZXhwb3J0IGNsYXNzIEZyZXF1ZW5jeSB7XG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihwcml2YXRlIF9fdmFsOiBudW1iZXIpIHtcbiAgICBpZiAodHlwZW9mIF9fdmFsICE9PSAnbnVtYmVyJyB8fCBpc05hTihfX3ZhbCkgfHwgX192YWwgPT09IEluZmluaXR5KVxuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0ZyZXF1ZW5jeSB2YWx1ZSBtdXN0IGJlIGEgbnVtYmVyJyk7XG4gICAgaWYgKHRoaXMuX192YWwgPCAwKVxuICAgIHRocm93IG5ldyBFcnJvcihgRnJlcXVlbmN5IHZhbHVlIGNhbm5vdCBiZSBuZWdhdGl2ZSAoJHtfX3ZhbH0pYCk7XG4gIH1cblxuICBwdWJsaWMga2h6KCkge1xuICAgIHJldHVybiB0aGlzLl9fdmFsICogMTAwMC4wO1xuICB9XG5cbiAgcHVibGljIG1oeigpIHtcbiAgICByZXR1cm4gdGhpcy5fX3ZhbCAqIDFfMDAwXzAwMC4wO1xuICB9XG5cbiAgcHVibGljIGh6KCkge1xuICAgIHJldHVybiB0aGlzLl9fdmFsO1xuICB9XG5cbiAgcHVibGljIGR0KCkge1xuICAgIHJldHVybiAxLjAgLyB0aGlzLl9fdmFsO1xuICB9XG5cbiAgcHVibGljIHZhbHVlT2YoKSB7XG4gICAgcmV0dXJuIHRoaXMuX192YWw7XG4gIH1cblxuICBwdWJsaWMgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIGAke3RoaXMuX192YWx9SHpgO1xuICB9XG5cbiAgcHVibGljIHRvSlNPTigpIHtcbiAgICByZXR1cm4gdGhpcy50b1N0cmluZygpO1xuICB9XG59IiwgImltcG9ydCB7IFRyYW5zZm9ybSwgVHJhbnNmb3JtT3B0aW9ucyB9IGZyb20gJ3N0cmVhbSc7XG5cbmV4cG9ydCB0eXBlIFBDTVR5cGUgPSBgcyR7MTYgfCAzMn0keydsJyB8ICdiJ31lYDtcblxuZXhwb3J0IGludGVyZmFjZSBQQ01UcmFuc2Zvcm1lck9wdGlvbnMgZXh0ZW5kcyBUcmFuc2Zvcm1PcHRpb25zIHtcbiAgdHlwZT86IFBDTVR5cGU7XG4gIGRpc2FibGVkPzogYm9vbGVhbjtcbiAgc2FtcGxlUmF0ZT86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIFBDTVRyYW5zZm9ybWVyIGV4dGVuZHMgVHJhbnNmb3JtIHtcbiAgcHVibGljIHJlYWRvbmx5IHR5cGU6IFBDTVR5cGUgPSAnczE2bGUnO1xuICBwdWJsaWMgYml0czogbnVtYmVyO1xuICBwdWJsaWMgYnl0ZXM6IG51bWJlcjtcbiAgcHVibGljIGV4dHJlbXVtOiBudW1iZXI7XG4gIHB1YmxpYyBkaXNhYmxlZCA9IGZhbHNlO1xuICBwdWJsaWMgc2FtcGxlUmF0ZSA9IDQ4MDAwO1xuICBwdWJsaWMgb25VcGRhdGUgPSAoKTogdm9pZCA9PiB7XG5cbiAgICAvKiBub29wICovfTtcblxuICBwdWJsaWMgY29uc3RydWN0b3Iob3B0aW9uczogUENNVHJhbnNmb3JtZXJPcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIG9wdGlvbnMudHlwZSA/Pz0gJ3MxNmxlJztcbiAgICB0aGlzLmRpc2FibGVkID0gISFvcHRpb25zLmRpc2FibGVkO1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zYW1wbGVSYXRlID09PSAnbnVtYmVyJyAmJiBvcHRpb25zLnNhbXBsZVJhdGUgPiAwKSB7XG4gICAgICB0aGlzLnNhbXBsZVJhdGUgPSBvcHRpb25zLnNhbXBsZVJhdGU7XG4gICAgfVxuXG4gICAgc3dpdGNoIChvcHRpb25zLnR5cGUpIHtcbiAgICAgIGNhc2UgJ3MxNmJlJzpcbiAgICAgIGNhc2UgJ3MxNmxlJzpcbiAgICAgICAgdGhpcy50eXBlID0gb3B0aW9ucy50eXBlO1xuICAgICAgICB0aGlzLmJpdHMgPSAxNjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdzMzJiZSc6XG4gICAgICBjYXNlICdzMzJsZSc6XG4gICAgICAgIHRoaXMudHlwZSA9IG9wdGlvbnMudHlwZTtcbiAgICAgICAgdGhpcy5iaXRzID0gMzI7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcbiAgICAgICAgICBgRXhwZWN0ZWQgdHlwZSB0byBiZSBvbmUgb2YgJHsoXG4gICAgICAgICAgWydzMTZiZScsICdzMTZsZScsICdzMzJiZScsICdzMzJsZSddIGFzIFBDTVR5cGVbXSkuXG4gICAgICAgICAgam9pbignLCAnKX0sIGdvdCBcIiR7b3B0aW9ucy50eXBlfVwiYFxuICAgICAgICApO1xuICAgIH1cblxuICAgIHRoaXMuYnl0ZXMgPSB0aGlzLmJpdHMgLyA4O1xuICAgIHRoaXMuZXh0cmVtdW0gPSBNYXRoLnBvdygyLCB0aGlzLmJpdHMgLSAxKTtcbiAgfVxuXG4gIHB1YmxpYyBkaXNhYmxlKCkge1xuICAgIHRoaXMuZGlzYWJsZWQgPSB0cnVlO1xuICB9XG5cbiAgcHVibGljIGVuYWJsZSgpIHtcbiAgICB0aGlzLmRpc2FibGVkID0gZmFsc2U7XG4gIH1cblxuICBwdWJsaWMgdG9nZ2xlKCkge1xuICAgIHRoaXMuZGlzYWJsZWQgPSAhdGhpcy5kaXNhYmxlZDtcblxuICAgIHJldHVybiB0aGlzLmRpc2FibGVkO1xuICB9XG5cbiAgcHVibGljIF9yZWFkSW50KGJ1ZmZlcjogQnVmZmVyLCBpbmRleDogbnVtYmVyKSB7XG4gICAgY29uc3QgbWV0aG9kID0gYHJlYWRJbnQke3RoaXMudHlwZS5cbiAgICBzdWJzdHJpbmcoMSkuXG4gICAgdG9VcHBlckNhc2UoKX1gIGFzIGByZWFkSW50JHsxNiB8IDMyfSR7J0wnIHwgJ0InfUVgO1xuICAgIHJldHVybiBidWZmZXJbbWV0aG9kXShpbmRleCk7XG4gIH1cblxuICBwdWJsaWMgX3dyaXRlSW50KGJ1ZmZlcjogQnVmZmVyLCBpbnQ6IG51bWJlciwgaW5kZXg6IG51bWJlcikge1xuICAgIGNvbnN0IG1ldGhvZCA9IGB3cml0ZUludCR7dGhpcy50eXBlLlxuICAgIHN1YnN0cmluZygxKS5cbiAgICB0b1VwcGVyQ2FzZSgpfWAgYXMgYHdyaXRlSW50JHsxNiB8IDMyfSR7J0wnIHwgJ0InfUVgO1xuICAgIHJldHVybiBidWZmZXJbbWV0aG9kXShpbnQsIGluZGV4KTtcbiAgfVxuXG4gIHB1YmxpYyBjbGFtcCh2YWw6IG51bWJlciwgbWF4ID0gdGhpcy5leHRyZW11bSAtIDEsIG1pbiA9IC10aGlzLmV4dHJlbXVtKSB7XG4gICAgcmV0dXJuIE1hdGgubWluKG1heCwgTWF0aC5tYXgobWluLCB2YWwpKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRTYW1wbGVSYXRlKHJhdGU6IG51bWJlcikge1xuICAgIHRoaXMuc2FtcGxlUmF0ZSA9IHJhdGU7XG4gICAgcmV0dXJuO1xuICB9XG59IiwgImltcG9ydCB7IFRyYW5zZm9ybUNhbGxiYWNrIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCB7IFBDTVRyYW5zZm9ybWVyLCBQQ01UcmFuc2Zvcm1lck9wdGlvbnMgfSBmcm9tICcuLi91dGlscyc7XG5pbXBvcnQgeyBCaXF1YWRGaWx0ZXIgfSBmcm9tICcuL0JpcXVhZCc7XG5pbXBvcnQge1xuICBCaXF1YWRGaWx0ZXJzLFxuICBDb2VmZmljaWVudHMsXG4gIEZpbHRlclR5cGUsXG4gIFFfQlVUVEVSV09SVEggfSBmcm9tXG4nLi9Db2VmZmljaWVudHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJpcXVhZFN0cmVhbU9wdGlvbnMgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lck9wdGlvbnMge1xuICBmaWx0ZXI/OiBCaXF1YWRGaWx0ZXJzO1xuICBRPzogbnVtYmVyO1xuICBjdXRvZmY/OiBudW1iZXI7XG4gIGdhaW4/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmlxdWFkRmlsdGVyVXBkYXRlRGF0YSB7XG4gIGZpbHRlcj86IEJpcXVhZEZpbHRlcnM7XG4gIFE/OiBudW1iZXI7XG4gIGN1dG9mZj86IG51bWJlcjtcbiAgZ2Fpbj86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIEJpcXVhZFN0cmVhbSBleHRlbmRzIFBDTVRyYW5zZm9ybWVyIHtcbiAgcHVibGljIGJpcXVhZCE6IEJpcXVhZEZpbHRlcjtcbiAgcHVibGljIGN1dG9mZiA9IDgwO1xuICBwdWJsaWMgZ2FpbiA9IDA7XG4gIHB1YmxpYyBiaXF1YWRGaWx0ZXIhOiBCaXF1YWRGaWx0ZXJzO1xuICBwdWJsaWMgUSA9IFFfQlVUVEVSV09SVEg7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihvcHRpb25zOiBCaXF1YWRTdHJlYW1PcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIGlmICgnY3V0b2ZmJyBpbiBvcHRpb25zKSB0aGlzLmN1dG9mZiA9IG9wdGlvbnMuY3V0b2ZmITtcbiAgICBpZiAoJ2dhaW4nIGluIG9wdGlvbnMpIHRoaXMuZ2FpbiA9IG9wdGlvbnMuZ2FpbiE7XG4gICAgaWYgKCdRJyBpbiBvcHRpb25zKSB0aGlzLlEgPSBvcHRpb25zLlEhO1xuICAgIGlmICgnYmlxdWFkRmlsdGVyJyBpbiBvcHRpb25zKSB7XG4gICAgICBpZiAoXG4gICAgICB0eXBlb2Ygb3B0aW9ucy5iaXF1YWRGaWx0ZXIgPT09ICdzdHJpbmcnIHx8XG4gICAgICB0eXBlb2Ygb3B0aW9ucy5iaXF1YWRGaWx0ZXIgPT09ICdudW1iZXInKVxuXG4gICAgICB0aGlzLmJpcXVhZEZpbHRlciA9IG9wdGlvbnMuZmlsdGVyITtcbiAgICAgIGlmICh0aGlzLmJpcXVhZEZpbHRlciAhPSBudWxsKSB7XG4gICAgICAgIHRoaXMuYmlxdWFkID0gbmV3IEJpcXVhZEZpbHRlcihcbiAgICAgICAgICBDb2VmZmljaWVudHMuZnJvbShcbiAgICAgICAgICAgIHRoaXMuYmlxdWFkRmlsdGVyLFxuICAgICAgICAgICAgdGhpcy5zYW1wbGVSYXRlLFxuICAgICAgICAgICAgdGhpcy5jdXRvZmYsXG4gICAgICAgICAgICB0aGlzLlEsXG4gICAgICAgICAgICB0aGlzLmdhaW5cbiAgICAgICAgICApXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldCBmaWx0ZXJzKCkge1xuICAgIHJldHVybiB0aGlzLmJpcXVhZEZpbHRlcjtcbiAgfVxuXG4gIHB1YmxpYyBzZXQgZmlsdGVycyhmOiBCaXF1YWRGaWx0ZXJzKSB7XG4gICAgaWYgKGYgPT0gbnVsbCB8fCB0eXBlb2YgZiA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGYgPT09ICdudW1iZXInKSB7XG4gICAgICB0aGlzLnVwZGF0ZSh7IGZpbHRlcjogZiB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgSW52YWxpZCBiaXF1YWQgZmlsdGVyIHR5cGUgXCIke2Z9XCJgKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0RmlsdGVyTmFtZSgpIHtcbiAgICBpZiAodGhpcy5iaXF1YWRGaWx0ZXIgPT0gbnVsbCkgcmV0dXJuIG51bGw7XG4gICAgaWYgKHR5cGVvZiB0aGlzLmJpcXVhZEZpbHRlciA9PT0gJ3N0cmluZycpIHJldHVybiB0aGlzLmJpcXVhZEZpbHRlcjtcbiAgICByZXR1cm4gT2JqZWN0LmVudHJpZXMoRmlsdGVyVHlwZSkuZmluZChcbiAgICAgIChyKSA9PiByWzFdID09PSB0aGlzLmJpcXVhZEZpbHRlclxuICAgICk/LlswXSBhcyBCaXF1YWRGaWx0ZXJzO1xuICB9XG5cbiAgcHVibGljIHVwZGF0ZShvcHRpb25zOiBCaXF1YWRGaWx0ZXJVcGRhdGVEYXRhKSB7XG4gICAgaWYgKCdjdXRvZmYnIGluIG9wdGlvbnMpIHRoaXMuY3V0b2ZmID0gb3B0aW9ucy5jdXRvZmYhO1xuICAgIGlmICgnZ2FpbicgaW4gb3B0aW9ucykgdGhpcy5nYWluID0gb3B0aW9ucy5nYWluITtcbiAgICBpZiAoJ1EnIGluIG9wdGlvbnMpIHRoaXMuUSA9IG9wdGlvbnMuUSE7XG4gICAgaWYgKCdmaWx0ZXInIGluIG9wdGlvbnMpIHRoaXMuYmlxdWFkRmlsdGVyID0gb3B0aW9ucy5maWx0ZXIhO1xuXG4gICAgaWYgKHRoaXMuYmlxdWFkRmlsdGVyICE9IG51bGwpIHtcbiAgICAgIHRoaXMuYmlxdWFkID0gbmV3IEJpcXVhZEZpbHRlcihcbiAgICAgICAgQ29lZmZpY2llbnRzLmZyb20oXG4gICAgICAgICAgdGhpcy5iaXF1YWRGaWx0ZXIsXG4gICAgICAgICAgdGhpcy5zYW1wbGVSYXRlLFxuICAgICAgICAgIHRoaXMuY3V0b2ZmLFxuICAgICAgICAgIHRoaXMuUSxcbiAgICAgICAgICB0aGlzLmdhaW5cbiAgICAgICAgKVxuICAgICAgKTtcbiAgICB9XG5cbiAgICB0aGlzLm9uVXBkYXRlPy4oKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRGaWx0ZXIoZmlsdGVyOiBCaXF1YWRGaWx0ZXJzKSB7XG4gICAgdGhpcy51cGRhdGUoeyBmaWx0ZXIgfSk7XG4gIH1cblxuICBwdWJsaWMgc2V0UShROiBudW1iZXIpIHtcbiAgICB0aGlzLnVwZGF0ZSh7IFEgfSk7XG4gIH1cblxuICBwdWJsaWMgc2V0Q3V0b2ZmKGYwOiBudW1iZXIpIHtcbiAgICB0aGlzLnVwZGF0ZSh7IGN1dG9mZjogZjAgfSk7XG4gIH1cblxuICBwdWJsaWMgc2V0R2FpbihkQjogbnVtYmVyKSB7XG4gICAgdGhpcy51cGRhdGUoeyBnYWluOiBkQiB9KTtcbiAgfVxuXG4gIHB1YmxpYyBfdHJhbnNmb3JtKFxuICBjaHVuazogQnVmZmVyLFxuICBlbmNvZGluZzogQnVmZmVyRW5jb2RpbmcsXG4gIGNhbGxiYWNrOiBUcmFuc2Zvcm1DYWxsYmFjaylcbiAge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8ICF0aGlzLmJpcXVhZCkge1xuICAgICAgdGhpcy5wdXNoKGNodW5rKTtcbiAgICAgIHJldHVybiBjYWxsYmFjaygpO1xuICAgIH1cblxuICAgIGNvbnN0IGVuZEluZGV4ID0gTWF0aC5mbG9vcihjaHVuay5sZW5ndGggLyAyKSAqIDI7XG4gICAgY29uc3QgeyBieXRlcyB9ID0gdGhpcztcblxuICAgIGZvciAobGV0IHNhbXBsZUluZGV4ID0gMDsgc2FtcGxlSW5kZXggPCBlbmRJbmRleDsgc2FtcGxlSW5kZXggKz0gYnl0ZXMpIHtcbiAgICAgIGNvbnN0IGludCA9IHRoaXMuX3JlYWRJbnQoY2h1bmssIHNhbXBsZUluZGV4KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuYmlxdWFkLnJ1bihpbnQpO1xuICAgICAgdGhpcy5fd3JpdGVJbnQoY2h1bmssIHRoaXMuY2xhbXAocmVzdWx0KSwgc2FtcGxlSW5kZXgpO1xuICAgIH1cblxuICAgIHRoaXMucHVzaChjaHVuayk7XG4gICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgRXF1YWxpemVyIH0gZnJvbSAnLi9FcXVhbGl6ZXInO1xuXG5leHBvcnQgdHlwZSBSZWFkSW50Q2FsbGJhY2sgPSAoYnVmZmVyOiBCdWZmZXIsIGluZGV4OiBudW1iZXIpID0+IG51bWJlcjtcbmV4cG9ydCB0eXBlIFdyaXRlSW50Q2FsbGJhY2sgPSAoXG5idWZmZXI6IEJ1ZmZlcixcbmludDogbnVtYmVyLFxuaW5kZXg6IG51bWJlcilcbj0+IG51bWJlcjtcblxuZXhwb3J0IGNsYXNzIENoYW5uZWxQcm9jZXNzb3Ige1xuICBwdWJsaWMgaGlzdG9yeTogbnVtYmVyW107XG4gIHB1YmxpYyBiYW5kTXVsdGlwbGllcnM6IG51bWJlcltdO1xuICBwdWJsaWMgY3VycmVudDogbnVtYmVyO1xuICBwdWJsaWMgbTE6IG51bWJlcjtcbiAgcHVibGljIG0yOiBudW1iZXI7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKGJhbmRNdWx0aXBsaWVyczogbnVtYmVyW10pIHtcbiAgICB0aGlzLmhpc3RvcnkgPSBuZXcgQXJyYXkoRXF1YWxpemVyLkJBTkRfQ09VTlQgKiA2KS5maWxsKDApO1xuICAgIHRoaXMuYmFuZE11bHRpcGxpZXJzID0gYmFuZE11bHRpcGxpZXJzO1xuICAgIHRoaXMuY3VycmVudCA9IDA7XG4gICAgdGhpcy5tMSA9IDI7XG4gICAgdGhpcy5tMiA9IDE7XG4gIH1cblxuICBwdWJsaWMgcHJvY2Vzc0ludChpbnQ6IG51bWJlcikge1xuICAgIGxldCByZXN1bHQgPSBpbnQgKiAwLjI1O1xuXG4gICAgZm9yIChsZXQgYmFuZEluZGV4ID0gMDsgYmFuZEluZGV4IDwgRXF1YWxpemVyLkJBTkRfQ09VTlQ7IGJhbmRJbmRleCsrKSB7XG4gICAgICBjb25zdCB4ID0gYmFuZEluZGV4ICogNjtcbiAgICAgIGNvbnN0IHkgPSB4ICsgMztcblxuICAgICAgY29uc3QgY29lZmZpY2llbnRzID0gRXF1YWxpemVyLkNvZWZmaWNpZW50czQ4MDAwW2JhbmRJbmRleF07XG5cbiAgICAgIGNvbnN0IGJhbmRSZXN1bHQgPVxuICAgICAgY29lZmZpY2llbnRzLmFscGhhICogKGludCAtIHRoaXMuaGlzdG9yeVt4ICsgdGhpcy5tMl0pICtcbiAgICAgIGNvZWZmaWNpZW50cy5nYW1tYSAqIHRoaXMuaGlzdG9yeVt5ICsgdGhpcy5tMV0gLVxuICAgICAgY29lZmZpY2llbnRzLmJldGEgKiB0aGlzLmhpc3RvcnlbeSArIHRoaXMubTJdO1xuXG4gICAgICB0aGlzLmhpc3RvcnlbeCArIHRoaXMuY3VycmVudF0gPSBpbnQ7XG4gICAgICB0aGlzLmhpc3RvcnlbeSArIHRoaXMuY3VycmVudF0gPSBiYW5kUmVzdWx0O1xuXG4gICAgICByZXN1bHQgKz0gYmFuZFJlc3VsdCAqIHRoaXMuYmFuZE11bHRpcGxpZXJzW2JhbmRJbmRleF07XG4gICAgfVxuXG4gICAgY29uc3QgdmFsID0gcmVzdWx0ICogNC4wO1xuXG4gICAgcmV0dXJuIHZhbDtcbiAgfVxuXG4gIHB1YmxpYyBwcm9jZXNzKFxuICBzYW1wbGVzOiBCdWZmZXIsXG4gIGV4dHJlbXVtID0gMTMxMDcyLFxuICBieXRlcyA9IDIsXG4gIHJlYWRJbnQ/OiBSZWFkSW50Q2FsbGJhY2ssXG4gIHdyaXRlSW50PzogV3JpdGVJbnRDYWxsYmFjaylcbiAge1xuICAgIGNvbnN0IGVuZEluZGV4ID0gTWF0aC5mbG9vcihzYW1wbGVzLmxlbmd0aCAvIDIpICogMjtcbiAgICBmb3IgKGxldCBzYW1wbGVJbmRleCA9IDA7IHNhbXBsZUluZGV4IDwgZW5kSW5kZXg7IHNhbXBsZUluZGV4ICs9IGJ5dGVzKSB7XG4gICAgICBjb25zdCBzYW1wbGUgPVxuICAgICAgcmVhZEludD8uKHNhbXBsZXMsIHNhbXBsZUluZGV4KSA/PyBzYW1wbGVzLnJlYWRJbnQxNkxFKHNhbXBsZUluZGV4KTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMucHJvY2Vzc0ludChzYW1wbGUpO1xuXG4gICAgICBjb25zdCB2YWwgPSBNYXRoLm1pbihleHRyZW11bSAtIDEsIE1hdGgubWF4KC1leHRyZW11bSwgcmVzdWx0KSk7XG4gICAgICB3cml0ZUludD8uKHNhbXBsZXMsIHZhbCwgc2FtcGxlSW5kZXgpID8/XG4gICAgICBzYW1wbGVzLndyaXRlSW50MTZMRSh2YWwsIHNhbXBsZUluZGV4KTtcblxuICAgICAgdGhpcy5zdGVwKCk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNhbXBsZXM7XG4gIH1cblxuICBwdWJsaWMgc3RlcCgpIHtcbiAgICBpZiAoKyt0aGlzLmN1cnJlbnQgPT09IDMpIHtcbiAgICAgIHRoaXMuY3VycmVudCA9IDA7XG4gICAgfVxuXG4gICAgaWYgKCsrdGhpcy5tMSA9PT0gMykge1xuICAgICAgdGhpcy5tMSA9IDA7XG4gICAgfVxuXG4gICAgaWYgKCsrdGhpcy5tMiA9PT0gMykge1xuICAgICAgdGhpcy5tMiA9IDA7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHJlc2V0KCkge1xuICAgIHRoaXMuaGlzdG9yeS5maWxsKDAuMCk7XG4gIH1cbn0iLCAiZXhwb3J0IGNsYXNzIEVxdWFsaXplckNvZWZmaWNpZW50cyB7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgcHVibGljIGJldGE6IG51bWJlcixcbiAgcHVibGljIGFscGhhOiBudW1iZXIsXG4gIHB1YmxpYyBnYW1tYTogbnVtYmVyKVxuICB7fVxuXG4gIHB1YmxpYyBzZXRCZXRhKHY6IG51bWJlcikge1xuICAgIHRoaXMuYmV0YSA9IHY7XG4gIH1cblxuICBwdWJsaWMgc2V0QWxwaGEodjogbnVtYmVyKSB7XG4gICAgdGhpcy5hbHBoYSA9IHY7XG4gIH1cblxuICBwdWJsaWMgc2V0R2FtbWEodjogbnVtYmVyKSB7XG4gICAgdGhpcy5nYW1tYSA9IHY7XG4gIH1cblxuICBwdWJsaWMgdG9KU09OKCkge1xuICAgIGNvbnN0IHsgYWxwaGEsIGJldGEsIGdhbW1hIH0gPSB0aGlzO1xuXG4gICAgcmV0dXJuIHsgYWxwaGEsIGJldGEsIGdhbW1hIH07XG4gIH1cbn0iLCAiZXhwb3J0IGNsYXNzIEVxdWFsaXplckNvbmZpZ3VyYXRpb24ge1xuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIGJhbmRNdWx0aXBsaWVyczogbnVtYmVyW10pIHt9XG5cbiAgcHVibGljIHNldEdhaW4oYmFuZDogbnVtYmVyLCB2YWx1ZTogbnVtYmVyKSB7XG4gICAgaWYgKHRoaXMuaXNWYWxpZEJhbmQoYmFuZCkpIHtcbiAgICAgIHRoaXMuYmFuZE11bHRpcGxpZXJzW2JhbmRdID0gTWF0aC5tYXgoTWF0aC5taW4odmFsdWUsIDEuMCksIC0wLjI1KTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0R2FpbihiYW5kOiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5pc1ZhbGlkQmFuZChiYW5kKSkge1xuICAgICAgcmV0dXJuIHRoaXMuYmFuZE11bHRpcGxpZXJzW2JhbmRdO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gMC4wO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBpc1ZhbGlkQmFuZChiYW5kOiBudW1iZXIpIHtcbiAgICByZXR1cm4gYmFuZCA+PSAwICYmIGJhbmQgPCB0aGlzLmJhbmRNdWx0aXBsaWVycy5sZW5ndGg7XG4gIH1cbn0iLCAiaW1wb3J0IHtcbiAgQ2hhbm5lbFByb2Nlc3NvcixcbiAgUmVhZEludENhbGxiYWNrLFxuICBXcml0ZUludENhbGxiYWNrIH0gZnJvbVxuJy4vQ2hhbm5lbFByb2Nlc3Nvcic7XG5pbXBvcnQgeyBFcXVhbGl6ZXJDb2VmZmljaWVudHMgfSBmcm9tICcuL0NvZWZmaWNpZW50cyc7XG5pbXBvcnQgeyBFcXVhbGl6ZXJDb25maWd1cmF0aW9uIH0gZnJvbSAnLi9FcXVhbGl6ZXJDb25maWd1cmF0aW9uJztcblxuZXhwb3J0IGludGVyZmFjZSBDaGFubmVsUHJvY2Vzc29ySW5wdXQge1xuICBkYXRhOiBCdWZmZXI7XG4gIHJlYWRJbnQ/OiBSZWFkSW50Q2FsbGJhY2s7XG4gIHdyaXRlSW50PzogV3JpdGVJbnRDYWxsYmFjaztcbiAgZXh0cmVtdW0/OiBudW1iZXI7XG4gIGJ5dGVzPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgRXF1YWxpemVyIGV4dGVuZHMgRXF1YWxpemVyQ29uZmlndXJhdGlvbiB7XG4gIHB1YmxpYyBzdGF0aWMgQkFORF9DT1VOVCA9IDE1IGFzIGNvbnN0O1xuICBwdWJsaWMgc3RhdGljIFNBTVBMRV9SQVRFID0gNDgwMDAgYXMgY29uc3Q7XG4gIHB1YmxpYyBzdGF0aWMgQ29lZmZpY2llbnRzNDgwMDAgPSBbXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS45ODQ3NTQ2NjY0ZS0xLCA3LjYyMjY2NjgxNDNlLTQsIDEuOTk4NDY0NzY1NiksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS45NzU2MTg0NjU0ZS0xLCAxLjIxOTA3NjcyODllLTMsIDEuOTk3NTM0NDY0NSksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS45NjE2MjYxMzc5ZS0xLCAxLjkxODY5MzEwNDFlLTMsIDEuOTk2MDk0NzM2OSksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS45MzkxNTc4NTQzZS0xLCAzLjA0MjEwNzI4NjVlLTMsIDEuOTkzNzQ0OTYxOCksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS45MDI4MzA3MjE1ZS0xLCA0Ljg1ODQ2MzkyNDJlLTMsIDEuOTg5ODQ2NTcwMiksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS44NDg1ODk3MjY0ZS0xLCA3LjU3MDUxMzY3OTVlLTMsIDEuOTgzNzk2MjU0MyksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS43NTg4NTEyNjU3ZS0xLCAxLjIwNTc0MzY3MTVlLTIsIDEuOTczMTc3MjQ0NyksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS42MjI4NTIxODE0ZS0xLCAxLjg4NTczOTA5MjhlLTIsIDEuOTU1NjE2NDY5NCksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS40MDgwOTMzMTMyZS0xLCAyLjk1OTUzMzQzMzhlLTIsIDEuOTI0MjA1NDM4NCksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOS4wNzAyMDU5MTk2ZS0xLCA0LjY0ODk3MDQwMjJlLTIsIDEuODY1MzQ3NjE2NiksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoOC41ODY4MDA0Mjg5ZS0xLCA3LjA2NTk5Nzg1NTNlLTIsIDEuNzYwMDQwMTMzNyksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoNy44NDA5NjEwNzg4ZS0xLCAxLjA3OTUxOTQ2MDZlLTEsIDEuNTQ1MDcyNTUyMiksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoNi44MzMyODYxMDAyZS0xLCAxLjU4MzM1Njk0OTllLTEsIDEuMTQyNjQ0NzE1NSksXG4gIG5ldyBFcXVhbGl6ZXJDb2VmZmljaWVudHMoXG4gICAgNS41MjY3NTE4MjI4ZS0xLFxuICAgIDIuMjM2NjI0MDg4NmUtMSxcbiAgICA0LjAxODYxOTA4MDNlLTFcbiAgKSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyhcbiAgICA0LjE4MTE4ODg0NDdlLTEsXG4gICAgMi45MDk0MDU1Nzc3ZS0xLFxuICAgIC03LjA5MDU5NDQyMjNlLTFcbiAgKV07XG5cbiAgcHVibGljIGNoYW5uZWxzOiBDaGFubmVsUHJvY2Vzc29yW10gPSBbXTtcbiAgcHVibGljIGNoYW5uZWxDb3VudDogbnVtYmVyO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihjaGFubmVsQ291bnQ6IG51bWJlciwgYmFuZE11bHRpcGxpZXJzOiBudW1iZXJbXSkge1xuICAgIHN1cGVyKGJhbmRNdWx0aXBsaWVycyk7XG4gICAgdGhpcy5jaGFubmVsQ291bnQgPSBjaGFubmVsQ291bnQ7XG4gICAgdGhpcy5jaGFubmVscyA9IHRoaXMuY3JlYXRlQ2hhbm5lbFByb2Nlc3NvcigpO1xuICB9XG5cbiAgcHVibGljIGNyZWF0ZUNoYW5uZWxQcm9jZXNzb3IoKSB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGg6IHRoaXMuY2hhbm5lbENvdW50IH0sICgpID0+IHtcbiAgICAgIHJldHVybiBuZXcgQ2hhbm5lbFByb2Nlc3Nvcih0aGlzLmJhbmRNdWx0aXBsaWVycyk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgcHJvY2VzcyhpbnB1dDogQ2hhbm5lbFByb2Nlc3NvcklucHV0W10pIHtcbiAgICByZXR1cm4gdGhpcy5jaGFubmVscy5tYXAoKGMsIGkpID0+IHtcbiAgICAgIGNvbnN0IHsgZGF0YSwgZXh0cmVtdW0sIHJlYWRJbnQsIHdyaXRlSW50LCBieXRlcyB9ID0gaW5wdXRbaV07XG5cbiAgICAgIHJldHVybiBjLnByb2Nlc3MoZGF0YSwgZXh0cmVtdW0sIGJ5dGVzLCByZWFkSW50LCB3cml0ZUludCk7XG4gICAgfSk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgVHJhbnNmb3JtQ2FsbGJhY2sgfSBmcm9tICdzdHJlYW0nO1xuaW1wb3J0IHsgUENNVHJhbnNmb3JtZXIsIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCB7IEVxdWFsaXplciB9IGZyb20gJy4vRXF1YWxpemVyJztcblxuZXhwb3J0IGludGVyZmFjZSBFcXVhbGl6ZXJTdHJlYW1PcHRpb25zIGV4dGVuZHMgUENNVHJhbnNmb3JtZXJPcHRpb25zIHtcbiAgYmFuZE11bHRpcGxpZXI/OiBFcXVhbGl6ZXJCYW5kW107XG4gIGNoYW5uZWxzPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEVxdWFsaXplckJhbmQge1xuICBiYW5kOiBudW1iZXI7XG4gIGdhaW46IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIEVxdWFsaXplclN0cmVhbSBleHRlbmRzIFBDTVRyYW5zZm9ybWVyIHtcbiAgcHVibGljIGJhbmRNdWx0aXBsaWVyczogbnVtYmVyW10gPSBuZXcgQXJyYXkoRXF1YWxpemVyLkJBTkRfQ09VTlQpLmZpbGwoMCk7XG4gIHB1YmxpYyBlcXVhbGl6ZXI6IEVxdWFsaXplcjtcbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM/OiBFcXVhbGl6ZXJTdHJlYW1PcHRpb25zKSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG5cbiAgICBvcHRpb25zID0gT2JqZWN0LmFzc2lnbihcbiAgICAgIHt9LFxuICAgICAge1xuICAgICAgICBiYW5kTXVsdGlwbGllcjogW10sXG4gICAgICAgIGNoYW5uZWxzOiAxXG4gICAgICB9LFxuICAgICAgb3B0aW9ucyB8fCB7fVxuICAgICk7XG5cbiAgICB0aGlzLmVxdWFsaXplciA9IG5ldyBFcXVhbGl6ZXIob3B0aW9ucy5jaGFubmVscyB8fCAxLCB0aGlzLmJhbmRNdWx0aXBsaWVycyk7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucy5iYW5kTXVsdGlwbGllcikpXG4gICAgdGhpcy5fcHJvY2Vzc0JhbmRzKG9wdGlvbnMuYmFuZE11bHRpcGxpZXIpO1xuICB9XG5cbiAgcHVibGljIF9wcm9jZXNzQmFuZHMobXVsdGlwbGllcjogRXF1YWxpemVyQmFuZFtdKSB7XG4gICAgZm9yIChjb25zdCBtdWwgb2YgbXVsdGlwbGllcikge1xuICAgICAgaWYgKG11bC5iYW5kID4gRXF1YWxpemVyLkJBTkRfQ09VTlQgLSAxIHx8IG11bC5iYW5kIDwgMClcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKFxuICAgICAgICBgQmFuZCB2YWx1ZSBvdXQgb2YgcmFuZ2UuIEV4cGVjdGVkID4wICYgPCR7XG4gICAgICAgIEVxdWFsaXplci5CQU5EX0NPVU5UIC0gMX0sIHJlY2VpdmVkIFwiJHtcbiAgICAgICAgbXVsLmJhbmR9XCJgXG4gICAgICApO1xuICAgICAgdGhpcy5lcXVhbGl6ZXIuc2V0R2FpbihtdWwuYmFuZCwgbXVsLmdhaW4pO1xuICAgIH1cblxuICAgIHRoaXMub25VcGRhdGU/LigpO1xuICB9XG5cbiAgcHVibGljIF90cmFuc2Zvcm0oXG4gIGNodW5rOiBCdWZmZXIsXG4gIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyxcbiAgY2FsbGJhY2s6IFRyYW5zZm9ybUNhbGxiYWNrKVxuICA6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSB7XG4gICAgICB0aGlzLnB1c2goY2h1bmspO1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgdGhpcy5lcXVhbGl6ZXIucHJvY2VzcyhbXG4gICAge1xuICAgICAgZGF0YTogY2h1bmssXG4gICAgICBleHRyZW11bTogdGhpcy5leHRyZW11bSxcbiAgICAgIHJlYWRJbnQ6IChiLCBpZHgpID0+IHRoaXMuX3JlYWRJbnQoYiwgaWR4KSxcbiAgICAgIHdyaXRlSW50OiAoYiwgaSwgaWR4KSA9PiB0aGlzLl93cml0ZUludChiLCBpLCBpZHgpLFxuICAgICAgYnl0ZXM6IHRoaXMuYnl0ZXNcbiAgICB9XVxuICAgICk7XG5cbiAgICB0aGlzLnB1c2goY2h1bmspO1xuXG4gICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0RVEoKSB7XG4gICAgcmV0dXJuIHRoaXMuYmFuZE11bHRpcGxpZXJzLm1hcCgobSwgaSkgPT4gKHtcbiAgICAgIGJhbmQ6IGksXG4gICAgICBnYWluOiBtXG4gICAgfSkpIGFzIEVxdWFsaXplckJhbmRbXTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRFUShiYW5kczogRXF1YWxpemVyQmFuZFtdKSB7XG4gICAgdGhpcy5fcHJvY2Vzc0JhbmRzKGJhbmRzKTtcbiAgfVxuXG4gIHB1YmxpYyByZXNldEVRKCkge1xuICAgIHRoaXMuX3Byb2Nlc3NCYW5kcyhcbiAgICAgIEFycmF5LmZyb20oXG4gICAgICAgIHtcbiAgICAgICAgICBsZW5ndGg6IEVxdWFsaXplci5CQU5EX0NPVU5UXG4gICAgICAgIH0sXG4gICAgICAgIChfLCBpKSA9PiAoe1xuICAgICAgICAgIGJhbmQ6IGksXG4gICAgICAgICAgZ2FpbjogMFxuICAgICAgICB9KVxuICAgICAgKVxuICAgICk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgVHJhbnNmb3JtQ2FsbGJhY2sgfSBmcm9tICdzdHJlYW0nO1xuaW1wb3J0IHsgUENNVHJhbnNmb3JtZXIsIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzJztcblxuLypcbk1vbm86IFswLCAxLCAyLCAzLCA0LCA1XVxuU3RlcmVvOiBbMCwgMSwgMCwgMSwgMiwgMywgMiwgMywgNCwgNSwgNCwgNV1cbiovXG5cbmV4cG9ydCB0eXBlIE1TVFN0cmF0ZWd5ID0gJ20ycycgfCAnczJtJztcblxuZXhwb3J0IGludGVyZmFjZSBNb25vU3RlcmVvVHJhbnNmb3JtZXJPcHRpb25zIGV4dGVuZHMgUENNVHJhbnNmb3JtZXJPcHRpb25zIHtcbiAgc3RyYXRlZ3k6IE1TVFN0cmF0ZWd5O1xufVxuXG5leHBvcnQgY2xhc3MgTW9ub1N0ZXJlb1RyYW5zZm9ybWVyIGV4dGVuZHMgUENNVHJhbnNmb3JtZXIge1xuICBwdWJsaWMgc3RyYXRlZ3k6IE1TVFN0cmF0ZWd5O1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihvcHRpb25zPzogTW9ub1N0ZXJlb1RyYW5zZm9ybWVyT3B0aW9ucykge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuICAgIGlmICghWydtMnMnLCAnczJtJ10uaW5jbHVkZXMob3B0aW9ucz8uc3RyYXRlZ3kgYXMgTVNUU3RyYXRlZ3kpKSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBTdHJhdGVneSBtdXN0IGJlIFwibTJzXCIgb3IgXCJzMm1cImApO1xuICAgIH1cblxuICAgIHRoaXMuc3RyYXRlZ3kgPSBvcHRpb25zIS5zdHJhdGVneTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRTdHJhdGVneShzdHJhdGVneTogTVNUU3RyYXRlZ3kpIHtcbiAgICB0aGlzLnN0cmF0ZWd5ID0gc3RyYXRlZ3k7XG4gIH1cblxuICBwdWJsaWMgX3RyYW5zZm9ybShcbiAgY2h1bms6IEJ1ZmZlcixcbiAgZW5jb2Rpbmc6IEJ1ZmZlckVuY29kaW5nLFxuICBjYWxsYmFjazogVHJhbnNmb3JtQ2FsbGJhY2spXG4gIDogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIHRoaXMucHVzaChjaHVuayk7XG4gICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICBjb25zdCBsZW4gPSBNYXRoLmZsb29yKGNodW5rLmxlbmd0aCAvIDIpICogMjtcblxuICAgIGlmICh0aGlzLnN0cmF0ZWd5ID09PSAnbTJzJykge1xuICAgICAgdGhpcy5wdXNoKHRoaXMudG9TdGVyZW8oY2h1bmssIGxlbikpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnB1c2godGhpcy50b01vbm8oY2h1bmssIGxlbikpO1xuICAgIH1cblxuICAgIHJldHVybiBjYWxsYmFjaygpO1xuICB9XG5cbiAgcHVibGljIHRvU3RlcmVvKHNhbXBsZTogQnVmZmVyLCBsZW46IG51bWJlcikge1xuICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlcztcbiAgICBjb25zdCBzdGVyZW9CdWZmZXIgPSBCdWZmZXIuYWxsb2MobGVuICogMik7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSArPSBieXRlcykge1xuICAgICAgc3RlcmVvQnVmZmVyW2kgKiAyICsgMF0gPSBzYW1wbGVbaV07XG4gICAgICBzdGVyZW9CdWZmZXJbaSAqIDIgKyAxXSA9IHNhbXBsZVtpICsgMV07XG4gICAgICBzdGVyZW9CdWZmZXJbaSAqIDIgKyAyXSA9IHNhbXBsZVtpXTtcbiAgICAgIHN0ZXJlb0J1ZmZlcltpICogMiArIDNdID0gc2FtcGxlW2kgKyAxXTtcbiAgICB9XG5cbiAgICByZXR1cm4gc3RlcmVvQnVmZmVyO1xuICB9XG5cbiAgcHVibGljIHRvTW9ubyhzYW1wbGU6IEJ1ZmZlciwgbGVuOiBudW1iZXIpIHtcbiAgICBjb25zdCBieXRlcyA9IHRoaXMuYnl0ZXM7XG4gICAgY29uc3QgbW9ub0J1ZmZlciA9IEJ1ZmZlci5hbGxvYyhNYXRoLmZsb29yKGxlbiAvIDIpKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpICs9IGJ5dGVzKSB7XG4gICAgICBtb25vQnVmZmVyW2ldID0gc2FtcGxlW2kgKiAyICsgMF07XG4gICAgICBtb25vQnVmZmVyW2kgKyAxXSA9IHNhbXBsZVtpICogMiArIDFdO1xuICAgIH1cblxuICAgIHJldHVybiBtb25vQnVmZmVyO1xuICB9XG59IiwgImV4cG9ydCAqIGZyb20gJy4vYmlxdWFkJztcbmV4cG9ydCAqIGZyb20gJy4vZHNwJztcbmV4cG9ydCAqIGZyb20gJy4vZXF1YWxpemVyJzsiLCAiaW1wb3J0IHsgQmlxdWFkRmlsdGVyLCBCaXF1YWRGaWx0ZXJzLCBDb2VmZmljaWVudHMgfSBmcm9tICcuLi8uLi9iaXF1YWQnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEFGQmlxdWFkQ29uZmlnIHtcbiAgYmlxdWFkOiBCaXF1YWRGaWx0ZXI7XG4gIHNhbXBsZTogbnVtYmVyO1xuICBjdXRvZmY6IG51bWJlcjtcbiAgZ2FpbjogbnVtYmVyO1xuICBmaWx0ZXI6IEJpcXVhZEZpbHRlcnM7XG4gIGNvZWZmaWNpZW50OiBDb2VmZmljaWVudHM7XG4gIFE6IG51bWJlcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5QmlxdWFkKGZpbHRlcmVyOiBCaXF1YWRGaWx0ZXIsIGludDogbnVtYmVyKSB7XG4gIHJldHVybiBmaWx0ZXJlci5ydW4oaW50KTtcbn0iLCAiZXhwb3J0IGludGVyZmFjZSBBRlB1bHNhdG9yQ29uZmlnIHtcbiAgaHo6IG51bWJlcjtcbiAgeDogbnVtYmVyO1xuICBkSTogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIEFGVHJlbW9sb0NvbmZpZyB7XG4gIHBoYXNlOiBudW1iZXI7XG4gIGRlcHRoOiBudW1iZXI7XG4gIGZyZXF1ZW5jeTogbnVtYmVyO1xufVxuXG5leHBvcnQgdHlwZSBBRlZpYnJhdG9Db25maWcgPSBBRlRyZW1vbG9Db25maWc7XG5cbmV4cG9ydCB0eXBlIExSID0gMCB8IDE7XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVB1bHNhdG9yKFxuY29uZmlnOiBBRlB1bHNhdG9yQ29uZmlnLFxuaW50OiBudW1iZXIsXG5jaGFubmVsOiBMUilcbntcbiAgY29uc3Qgc2luID0gTWF0aC5zaW4oY29uZmlnLngpO1xuICBjb25zdCBjdXJyZW50Q2hhbm5lbFZhbCA9IGNoYW5uZWwgPT09IDAgPyBzaW4gOiAtc2luO1xuICBjb25zdCByZXMgPSBpbnQgKiAoY3VycmVudENoYW5uZWxWYWwgKyAxLjApIC8gMi4wO1xuXG4gIGNvbmZpZy54ICs9IGNvbmZpZy5kSTtcblxuICByZXR1cm4gcmVzO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlUcmVtb2xvKFxuY29uZmlnOiBBRlRyZW1vbG9Db25maWcsXG5pbnQ6IG51bWJlcixcbnNhbXBsZVJhdGU6IG51bWJlcilcbntcbiAgY29uc3QgZk9mZnNldCA9IDEuMCAtIGNvbmZpZy5kZXB0aDtcbiAgY29uc3QgbW9kU2lnbmFsID0gZk9mZnNldCArIGNvbmZpZy5kZXB0aCAqIE1hdGguc2luKGNvbmZpZy5waGFzZSk7XG4gIGNvbmZpZy5waGFzZSArPSAyICogTWF0aC5QSSAvIHNhbXBsZVJhdGUgKiBjb25maWcuZnJlcXVlbmN5O1xuICByZXR1cm4gbW9kU2lnbmFsICogaW50O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlWaWJyYXRvKFxuY29uZmlnOiBBRlZpYnJhdG9Db25maWcsXG5pbnQ6IG51bWJlcixcbnNhbXBsZVJhdGU6IG51bWJlcilcbntcbiAgY29uc3QgZk9mZnNldCA9IDEuMCAtIGNvbmZpZy5kZXB0aDtcbiAgY29uc3QgbW9kU2lnbmFsID1cbiAgZk9mZnNldCArIGNvbmZpZy5kZXB0aCAqIE1hdGguc2luKDIgKiBNYXRoLlBJICogY29uZmlnLnBoYXNlKTtcbiAgY29uZmlnLnBoYXNlICs9IDIgKiBNYXRoLlBJIC8gc2FtcGxlUmF0ZSAqIGNvbmZpZy5mcmVxdWVuY3k7XG4gIHJldHVybiBtb2RTaWduYWwgKiBpbnQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVZvbHVtZSh2b2w6IG51bWJlciwgaW50OiBudW1iZXIpIHtcbiAgcmV0dXJuIHZvbCAqIGludDtcbn0iLCAiaW1wb3J0IHsgRXF1YWxpemVyIH0gZnJvbSAnLi4vLi4vZXF1YWxpemVyJztcblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5RXF1YWxpemF0aW9uKGVxOiBFcXVhbGl6ZXIsIGludDogbnVtYmVyKSB7XG4gIGNvbnN0IHByb2Nlc3NvciA9IGVxLmNoYW5uZWxzWzBdO1xuICBjb25zdCByZXN1bHQgPSBwcm9jZXNzb3IucHJvY2Vzc0ludChpbnQpO1xuICBwcm9jZXNzb3Iuc3RlcCgpO1xuICByZXR1cm4gcmVzdWx0O1xufSIsICJpbXBvcnQgeyBUcmFuc2Zvcm1DYWxsYmFjayB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBQQ01UcmFuc2Zvcm1lciwgUENNVHJhbnNmb3JtZXJPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IHtcbiAgQUZQdWxzYXRvckNvbmZpZyxcbiAgQUZUcmVtb2xvQ29uZmlnLFxuICBBRlZpYnJhdG9Db25maWcsXG4gIExSLFxuICBhcHBseVB1bHNhdG9yLFxuICBhcHBseVRyZW1vbG8sXG4gIGFwcGx5VmlicmF0byB9IGZyb21cbicuL3RyYW5zZm9ybWVycyc7XG5pbXBvcnQgeyBFcXVhbGl6ZXJCYW5kIH0gZnJvbSAnLi4vZXF1YWxpemVyJztcblxuZXhwb3J0IGNvbnN0IEF1ZGlvRmlsdGVycyA9IHtcbiAgJzhEJzogJzhEJyxcbiAgVHJlbW9sbzogJ1RyZW1vbG8nLFxuICBWaWJyYXRvOiAnVmlicmF0bydcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCB0eXBlIFBDTUZpbHRlcnMgPSBrZXlvZiB0eXBlb2YgQXVkaW9GaWx0ZXJzO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBDTUZpbHRlcmVyT3B0aW9ucyBleHRlbmRzIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB7XG4gIGZpbHRlcnM/OiBQQ01GaWx0ZXJzW107XG59XG5cbmV4cG9ydCBjb25zdCBBRl9OSUdIVENPUkVfUkFURSA9IDEuMyBhcyBjb25zdDtcbmV4cG9ydCBjb25zdCBBRl9WQVBPUldBVkVfUkFURSA9IDAuOCBhcyBjb25zdDtcblxuZXhwb3J0IGNvbnN0IEJBU1NfRVFfQkFORFM6IEVxdWFsaXplckJhbmRbXSA9IEFycmF5LmZyb20oXG4gIHsgbGVuZ3RoOiAzIH0sXG4gIChfLCBpKSA9PiAoe1xuICAgIGJhbmQ6IGksXG4gICAgZ2FpbjogMC4yNVxuICB9KVxuKTtcblxuLy8gYmFzZWQgb24gbGF2YWRzcFxuZXhwb3J0IGNsYXNzIEF1ZGlvRmlsdGVyIGV4dGVuZHMgUENNVHJhbnNmb3JtZXIge1xuICBwdWJsaWMgZmlsdGVyczogUENNRmlsdGVyc1tdID0gW107XG4gIHB1YmxpYyB0YXJnZXRTYW1wbGVSYXRlID0gdGhpcy5zYW1wbGVSYXRlO1xuXG4gIHB1YmxpYyBwdWxzYXRvckNvbmZpZzogQUZQdWxzYXRvckNvbmZpZyA9IHtcbiAgICBoejogMC4wMixcbiAgICB4OiAwLFxuICAgIGRJOiAwLjAwMDAwMzkyNjk5MDgxNjk4NzI0MVxuICB9O1xuXG4gIHB1YmxpYyB0cmVtb2xvQ29uZmlnOiBBRlRyZW1vbG9Db25maWcgPSB7XG4gICAgcGhhc2U6IDAsXG4gICAgZGVwdGg6IDAuNSxcbiAgICBmcmVxdWVuY3k6IDUuMFxuICB9O1xuXG4gIHB1YmxpYyB2aWJyYXRvQ29uZmlnOiBBRlZpYnJhdG9Db25maWcgPSB7XG4gICAgcGhhc2U6IDAsXG4gICAgZGVwdGg6IDAuNSxcbiAgICBmcmVxdWVuY3k6IDUuMFxuICB9O1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihvcHRpb25zPzogUENNRmlsdGVyZXJPcHRpb25zKSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG5cbiAgICBpZiAob3B0aW9ucyAmJiBBcnJheS5pc0FycmF5KG9wdGlvbnMuZmlsdGVycykpIHtcbiAgICAgIHRoaXMuc2V0RmlsdGVycyhvcHRpb25zLmZpbHRlcnMpO1xuICAgIH1cblxuICAgIHRoaXMub25VcGRhdGU/LigpO1xuICB9XG5cbiAgcHVibGljIHNldFRhcmdldFNhbXBsZVJhdGUocmF0ZTogbnVtYmVyKSB7XG4gICAgdGhpcy50YXJnZXRTYW1wbGVSYXRlID0gcmF0ZSB8fCB0aGlzLnNhbXBsZVJhdGU7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgcHVibGljIHNldFB1bHNhdG9yKGh6OiBudW1iZXIpIHtcbiAgICBoeiAvPSA0OyAvLyBtYXRjaCBmZm1wZWdcbiAgICB0aGlzLnB1bHNhdG9yQ29uZmlnLmh6ID0gaHo7XG4gICAgY29uc3Qgc2FtcGxlc1BlckN5Y2xlID0gdGhpcy50YXJnZXRTYW1wbGVSYXRlIC8gKGh6ICogMiAqIE1hdGguUEkpO1xuICAgIHRoaXMucHVsc2F0b3JDb25maWcuZEkgPSBoeiA9PT0gMCA/IDAgOiAxIC8gc2FtcGxlc1BlckN5Y2xlO1xuXG4gICAgdGhpcy5vblVwZGF0ZT8uKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHB1bHNhdG9yKCkge1xuICAgIHJldHVybiB0aGlzLnB1bHNhdG9yQ29uZmlnLmh6O1xuICB9XG5cbiAgcHVibGljIHNldFRyZW1vbG8oe1xuICAgIGRlcHRoID0gdGhpcy50cmVtb2xvQ29uZmlnLmRlcHRoLFxuICAgIGZyZXF1ZW5jeSA9IHRoaXMudHJlbW9sb0NvbmZpZy5mcmVxdWVuY3ksXG4gICAgcGhhc2UgPSB0aGlzLnRyZW1vbG9Db25maWcucGhhc2VcbiAgfTogUGFydGlhbDxBRlRyZW1vbG9Db25maWc+KSB7XG4gICAgaWYgKHR5cGVvZiBkZXB0aCA9PT0gJ251bWJlcicpIHRoaXMudHJlbW9sb0NvbmZpZy5kZXB0aCA9IGRlcHRoO1xuICAgIGlmICh0eXBlb2YgZnJlcXVlbmN5ID09PSAnbnVtYmVyJykgdGhpcy50cmVtb2xvQ29uZmlnLmZyZXF1ZW5jeSA9IGZyZXF1ZW5jeTtcbiAgICBpZiAodHlwZW9mIHBoYXNlID09PSAnbnVtYmVyJykgdGhpcy50cmVtb2xvQ29uZmlnLnBoYXNlID0gcGhhc2U7XG5cbiAgICB0aGlzLm9uVXBkYXRlPy4oKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRWaWJyYXRvKHtcbiAgICBkZXB0aCA9IHRoaXMudmlicmF0b0NvbmZpZy5kZXB0aCxcbiAgICBmcmVxdWVuY3kgPSB0aGlzLnZpYnJhdG9Db25maWcuZnJlcXVlbmN5LFxuICAgIHBoYXNlID0gdGhpcy52aWJyYXRvQ29uZmlnLnBoYXNlXG4gIH06IFBhcnRpYWw8QUZWaWJyYXRvQ29uZmlnPikge1xuICAgIGlmICh0eXBlb2YgZGVwdGggPT09ICdudW1iZXInKSB0aGlzLnZpYnJhdG9Db25maWcuZGVwdGggPSBkZXB0aDtcbiAgICBpZiAodHlwZW9mIGZyZXF1ZW5jeSA9PT0gJ251bWJlcicpIHRoaXMudmlicmF0b0NvbmZpZy5mcmVxdWVuY3kgPSBmcmVxdWVuY3k7XG4gICAgaWYgKHR5cGVvZiBwaGFzZSA9PT0gJ251bWJlcicpIHRoaXMudmlicmF0b0NvbmZpZy5waGFzZSA9IHBoYXNlO1xuXG4gICAgdGhpcy5vblVwZGF0ZT8uKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHRyZW1vbG8oKSB7XG4gICAgcmV0dXJuIHRoaXMudHJlbW9sb0NvbmZpZztcbiAgfVxuXG4gIHB1YmxpYyBzZXRGaWx0ZXJzKGZpbHRlcnM6IFBDTUZpbHRlcnNbXSkge1xuICAgIGlmICghQXJyYXkuaXNBcnJheShmaWx0ZXJzKSB8fCAhZmlsdGVycy5ldmVyeSgocikgPT4gciBpbiBBdWRpb0ZpbHRlcnMpKSB7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdGhpcy5maWx0ZXJzID0gZmlsdGVycztcblxuICAgIHRoaXMub25VcGRhdGU/LigpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwdWJsaWMgX3RyYW5zZm9ybShcbiAgY2h1bms6IEJ1ZmZlcixcbiAgZW5jb2Rpbmc6IEJ1ZmZlckVuY29kaW5nLFxuICBjYWxsYmFjazogVHJhbnNmb3JtQ2FsbGJhY2spXG4gIDogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgIXRoaXMuZmlsdGVycy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBjYWxsYmFjayhudWxsLCBjaHVuayk7XG4gICAgfVxuXG4gICAgY29uc3QgbGVuID0gTWF0aC5mbG9vcihjaHVuay5sZW5ndGggLyAyKSAqIDI7XG4gICAgY29uc3QgeyBieXRlcyB9ID0gdGhpcztcblxuICAgIC8vIGxlZnQtcmlnaHQgY2hhbm5lbFxuICAgIGxldCBMID0gZmFsc2U7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSArPSBieXRlcykge1xuICAgICAgY29uc3QgaW50ID0gdGhpcy5fcmVhZEludChjaHVuaywgaSk7XG4gICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuYXBwbHlGaWx0ZXJzKGludCwgKyhMID0gIUwpIGFzIExSKTtcbiAgICAgIHRoaXMuX3dyaXRlSW50KGNodW5rLCB0aGlzLmNsYW1wKHZhbHVlKSwgaSk7XG4gICAgfVxuXG4gICAgdGhpcy5wdXNoKGNodW5rKTtcblxuICAgIHJldHVybiBjYWxsYmFjaygpO1xuICB9XG5cbiAgcHVibGljIGdldCBjdXJyZW50U2FtcGxlUmF0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy50YXJnZXRTYW1wbGVSYXRlIHx8IHRoaXMuc2FtcGxlUmF0ZTtcbiAgfVxuXG4gIHB1YmxpYyBhcHBseUZpbHRlcnMoYnl0ZTogbnVtYmVyLCBjaGFubmVsOiBMUikge1xuICAgIGlmICh0aGlzLmZpbHRlcnMubGVuZ3RoKSB7XG4gICAgICBmb3IgKGNvbnN0IGZpbHRlciBvZiB0aGlzLmZpbHRlcnMpIHtcbiAgICAgICAgaWYgKGZpbHRlciA9PT0gJzhEJykge1xuICAgICAgICAgIGJ5dGUgPSBhcHBseVB1bHNhdG9yKHRoaXMucHVsc2F0b3JDb25maWcsIGJ5dGUsIGNoYW5uZWwpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZpbHRlciA9PT0gJ1RyZW1vbG8nKSB7XG4gICAgICAgICAgYnl0ZSA9IGFwcGx5VHJlbW9sbyh0aGlzLnRyZW1vbG9Db25maWcsIGJ5dGUsIHRoaXMuY3VycmVudFNhbXBsZVJhdGUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGZpbHRlciA9PT0gJ1ZpYnJhdG8nKSB7XG4gICAgICAgICAgYnl0ZSA9IGFwcGx5VmlicmF0byh0aGlzLnZpYnJhdG9Db25maWcsIGJ5dGUsIHRoaXMuY3VycmVudFNhbXBsZVJhdGUpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIGJ5dGU7XG4gIH1cbn0iLCAiaW1wb3J0IHsgUENNVHJhbnNmb3JtZXIsIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGludGVyZmFjZSBQQ01SZXNhbXBsZXJPcHRpb25zIGV4dGVuZHMgUENNVHJhbnNmb3JtZXJPcHRpb25zIHtcbiAgaW5wdXRTYW1wbGVSYXRlOiBudW1iZXI7XG4gIHRhcmdldFNhbXBsZVJhdGU6IG51bWJlcjtcbiAgY2hhbm5lbHM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmVzYW1wbGVQYXJhbWV0ZXJzIHtcbiAgY3VycmVudEZpbHRlcjogQ29tbW9uUmVzYW1wbGVyRmlsdGVyUHJlc2V0IHwgbnVsbDtcbiAgaW5wdXRTYW1wbGVSYXRlOiBudW1iZXI7XG4gIGNoYW5uZWxzOiBudW1iZXI7XG4gIHNhbXBsZVJhdGU6IG51bWJlcjtcbn1cblxuZXhwb3J0IHR5cGUgQ29tbW9uUmVzYW1wbGVyRmlsdGVyUHJlc2V0ID0gJ25pZ2h0Y29yZScgfCAndmFwb3J3YXZlJztcblxuZXhwb3J0IGNsYXNzIFBDTVJlc2FtcGxlciBleHRlbmRzIFBDTVRyYW5zZm9ybWVyIHtcbiAgcHJpdmF0ZSByZWFkb25seSBpbnB1dFNhbXBsZVJhdGU6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBjaGFubmVsczogbnVtYmVyO1xuICBwcml2YXRlIGJ1ZmZlcjogQnVmZmVyO1xuICBwdWJsaWMgY3VycmVudEZpbHRlcjogQ29tbW9uUmVzYW1wbGVyRmlsdGVyUHJlc2V0IHwgbnVsbCA9IG51bGw7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM/OiBQQ01SZXNhbXBsZXJPcHRpb25zKSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG5cbiAgICB0aGlzLmlucHV0U2FtcGxlUmF0ZSA9IG9wdGlvbnM/LmlucHV0U2FtcGxlUmF0ZSA/PyA0ODAwMDtcbiAgICB0aGlzLmNoYW5uZWxzID0gb3B0aW9ucz8uY2hhbm5lbHMgPz8gMjtcbiAgICB0aGlzLmJ1ZmZlciA9IEJ1ZmZlci5hbGxvYygwKTtcblxuICAgIGlmICh0aGlzLmlucHV0U2FtcGxlUmF0ZSA8IDEpIHtcbiAgICAgIHRoaXMuaW5wdXRTYW1wbGVSYXRlID0gNDgwMDA7XG4gICAgfVxuXG4gICAgaWYgKG9wdGlvbnM/LnRhcmdldFNhbXBsZVJhdGUpIHtcbiAgICAgIHRoaXMuc2V0U2FtcGxlUmF0ZShvcHRpb25zPy50YXJnZXRTYW1wbGVSYXRlKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgc2V0RmlsdGVyKGZpbHRlcjogQ29tbW9uUmVzYW1wbGVyRmlsdGVyUHJlc2V0IHwgbnVsbCkge1xuICAgIGlmICh0aGlzLmN1cnJlbnRGaWx0ZXIgPT09IGZpbHRlcikgcmV0dXJuO1xuXG4gICAgc3dpdGNoIChmaWx0ZXIpIHtcbiAgICAgIGNhc2UgJ25pZ2h0Y29yZSc6XG4gICAgICAgIHRoaXMuc2V0U2FtcGxlUmF0ZSh0aGlzLmlucHV0U2FtcGxlUmF0ZSAqIDEuMjUpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3ZhcG9yd2F2ZSc6XG4gICAgICAgIHRoaXMuc2V0U2FtcGxlUmF0ZSh0aGlzLmlucHV0U2FtcGxlUmF0ZSAqIDAuOCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgZGVmYXVsdDpcbiAgICAgICAgdGhpcy5zZXRTYW1wbGVSYXRlKHRoaXMuaW5wdXRTYW1wbGVSYXRlKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgdGhpcy5jdXJyZW50RmlsdGVyID0gZmlsdGVyO1xuICB9XG5cbiAgcHVibGljIGdldFBhcmFtZXRlcnMoKTogUmVzYW1wbGVQYXJhbWV0ZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgY3VycmVudEZpbHRlcjogdGhpcy5jdXJyZW50RmlsdGVyLFxuICAgICAgaW5wdXRTYW1wbGVSYXRlOiB0aGlzLmlucHV0U2FtcGxlUmF0ZSxcbiAgICAgIGNoYW5uZWxzOiB0aGlzLmNoYW5uZWxzLFxuICAgICAgc2FtcGxlUmF0ZTogdGhpcy5zYW1wbGVSYXRlXG4gICAgfTtcbiAgfVxuXG4gIHB1YmxpYyB0b2dnbGVGaWx0ZXIoZmlsdGVyOiBDb21tb25SZXNhbXBsZXJGaWx0ZXJQcmVzZXQpOiBib29sZWFuIHtcbiAgICBjb25zdCBzYW1lID0gdGhpcy5jdXJyZW50RmlsdGVyID09PSBmaWx0ZXI7XG4gICAgdGhpcy5zZXRGaWx0ZXIoc2FtZSA/IG51bGwgOiBmaWx0ZXIpO1xuXG4gICAgcmV0dXJuICFzYW1lO1xuICB9XG5cbiAgcHVibGljIGdldFJhdGlvKCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuaW5wdXRTYW1wbGVSYXRlID09PSAwKSByZXR1cm4gMTtcblxuICAgIHJldHVybiB0aGlzLnNhbXBsZVJhdGUgLyB0aGlzLmlucHV0U2FtcGxlUmF0ZTtcbiAgfVxuXG4gIHByaXZhdGUgcmVzYW1wbGUoaW5wdXQ6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gICAgY29uc3QgYnl0ZXNQZXJGcmFtZSA9IHRoaXMuYnl0ZXMgKiB0aGlzLmNoYW5uZWxzO1xuICAgIGNvbnN0IGlucHV0RnJhbWVzID0gTWF0aC5mbG9vcihpbnB1dC5sZW5ndGggLyBieXRlc1BlckZyYW1lKTtcbiAgICBjb25zdCBvdXRwdXRGcmFtZXMgPSBNYXRoLmZsb29yKFxuICAgICAgaW5wdXRGcmFtZXMgKiB0aGlzLmlucHV0U2FtcGxlUmF0ZSAvIHRoaXMuc2FtcGxlUmF0ZVxuICAgICk7XG4gICAgY29uc3Qgb3V0cHV0ID0gQnVmZmVyLmFsbG9jKG91dHB1dEZyYW1lcyAqIGJ5dGVzUGVyRnJhbWUpO1xuXG4gICAgZm9yIChsZXQgb3V0RnJhbWUgPSAwOyBvdXRGcmFtZSA8IG91dHB1dEZyYW1lczsgb3V0RnJhbWUrKykge1xuICAgICAgY29uc3QgaW5Qb3MgPSBvdXRGcmFtZSAqIHRoaXMuc2FtcGxlUmF0ZSAvIHRoaXMuaW5wdXRTYW1wbGVSYXRlO1xuICAgICAgY29uc3QgaW5GcmFtZSA9IE1hdGguZmxvb3IoaW5Qb3MpO1xuXG4gICAgICBpZiAoXG4gICAgICBpbkZyYW1lID49IGlucHV0RnJhbWVzIC0gMSB8fFxuICAgICAgKGluRnJhbWUgKyAxKSAqIGJ5dGVzUGVyRnJhbWUgKyAodGhpcy5jaGFubmVscyAtIDEpICogdGhpcy5ieXRlcyA+XG4gICAgICBpbnB1dC5sZW5ndGgpXG4gICAgICB7XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBmcmFjdGlvbiA9IGluUG9zIC0gaW5GcmFtZTtcblxuICAgICAgZm9yIChsZXQgY2hhbm5lbCA9IDA7IGNoYW5uZWwgPCB0aGlzLmNoYW5uZWxzOyBjaGFubmVsKyspIHtcbiAgICAgICAgY29uc3QgcG9zMSA9IGluRnJhbWUgKiBieXRlc1BlckZyYW1lICsgY2hhbm5lbCAqIHRoaXMuYnl0ZXM7XG4gICAgICAgIGNvbnN0IHBvczIgPSAoaW5GcmFtZSArIDEpICogYnl0ZXNQZXJGcmFtZSArIGNoYW5uZWwgKiB0aGlzLmJ5dGVzO1xuXG4gICAgICAgIGlmIChcbiAgICAgICAgcG9zMSArIHRoaXMuYnl0ZXMgPiBpbnB1dC5sZW5ndGggfHxcbiAgICAgICAgcG9zMiArIHRoaXMuYnl0ZXMgPiBpbnB1dC5sZW5ndGgpXG4gICAgICAgIHtcbiAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNhbXBsZTEgPSB0aGlzLl9yZWFkSW50KGlucHV0LCBwb3MxKTtcbiAgICAgICAgY29uc3Qgc2FtcGxlMiA9IHRoaXMuX3JlYWRJbnQoaW5wdXQsIHBvczIpO1xuXG4gICAgICAgIGNvbnN0IGludGVycG9sYXRlZCA9IHNhbXBsZTEgKyBmcmFjdGlvbiAqIChzYW1wbGUyIC0gc2FtcGxlMSk7XG4gICAgICAgIGNvbnN0IGNsYW1wZWQgPSB0aGlzLmNsYW1wKE1hdGgucm91bmQoaW50ZXJwb2xhdGVkKSk7XG5cbiAgICAgICAgY29uc3Qgb3V0UG9zID0gb3V0RnJhbWUgKiBieXRlc1BlckZyYW1lICsgY2hhbm5lbCAqIHRoaXMuYnl0ZXM7XG4gICAgICAgIHRoaXMuX3dyaXRlSW50KG91dHB1dCwgY2xhbXBlZCwgb3V0UG9zKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gb3V0cHV0O1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIF90cmFuc2Zvcm0oXG4gIGNodW5rOiBCdWZmZXIsXG4gIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyxcbiAgY2FsbGJhY2s6IChlcnJvcj86IEVycm9yIHwgbnVsbCwgZGF0YT86IEJ1ZmZlcikgPT4gdm9pZClcbiAgOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCB0aGlzLnNhbXBsZVJhdGUgPT09IHRoaXMuaW5wdXRTYW1wbGVSYXRlKSB7XG4gICAgICB0aGlzLnB1c2goY2h1bmspO1xuICAgICAgY2FsbGJhY2soKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLmJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW3RoaXMuYnVmZmVyLCBjaHVua10pO1xuXG4gICAgY29uc3QgYnl0ZXNQZXJGcmFtZSA9IHRoaXMuYnl0ZXMgKiB0aGlzLmNoYW5uZWxzO1xuICAgIGNvbnN0IG1pbkZyYW1lc05lZWRlZCA9IE1hdGguY2VpbChcbiAgICAgIGJ5dGVzUGVyRnJhbWUgKiAodGhpcy5pbnB1dFNhbXBsZVJhdGUgLyB0aGlzLnNhbXBsZVJhdGUpXG4gICAgKTtcbiAgICBjb25zdCBjb21wbGV0ZUZyYW1lcyA9IE1hdGguZmxvb3IodGhpcy5idWZmZXIubGVuZ3RoIC8gYnl0ZXNQZXJGcmFtZSkgLSAxO1xuXG4gICAgaWYgKGNvbXBsZXRlRnJhbWVzID49IG1pbkZyYW1lc05lZWRlZCkge1xuICAgICAgY29uc3QgcHJvY2Vzc1NpemUgPSBjb21wbGV0ZUZyYW1lcyAqIGJ5dGVzUGVyRnJhbWU7XG4gICAgICBjb25zdCB0b1Byb2Nlc3MgPSB0aGlzLmJ1ZmZlci5zbGljZSgwLCBwcm9jZXNzU2l6ZSk7XG4gICAgICB0aGlzLmJ1ZmZlciA9IHRoaXMuYnVmZmVyLnNsaWNlKHByb2Nlc3NTaXplKTtcblxuICAgICAgY29uc3QgcmVzYW1wbGVkID0gdGhpcy5yZXNhbXBsZSh0b1Byb2Nlc3MpO1xuICAgICAgdGhpcy5wdXNoKHJlc2FtcGxlZCk7XG4gICAgfVxuXG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZSBfZmx1c2goXG4gIGNhbGxiYWNrOiAoZXJyb3I/OiBFcnJvciB8IG51bGwsIGRhdGE/OiBCdWZmZXIpID0+IHZvaWQpXG4gIDogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIGNhbGxiYWNrKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuYnVmZmVyLmxlbmd0aCA+IDApIHtcbiAgICAgIGNvbnN0IHJlc2FtcGxlZCA9IHRoaXMucmVzYW1wbGUodGhpcy5idWZmZXIpO1xuICAgICAgdGhpcy5wdXNoKHJlc2FtcGxlZCk7XG4gICAgfVxuICAgIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgc2V0U2FtcGxlUmF0ZShyYXRlOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAocmF0ZSA9PT0gdGhpcy5zYW1wbGVSYXRlKSByZXR1cm47XG5cbiAgICBpZiAocmF0ZSA8IDEpIHtcbiAgICAgIHRocm93IG5ldyBSYW5nZUVycm9yKCdTYW1wbGUgcmF0ZSBtdXN0IGJlIGdyZWF0ZXIgdGhhbiAwJyk7XG4gICAgfVxuXG4gICAgc3VwZXIuc2V0U2FtcGxlUmF0ZShyYXRlKTtcbiAgICB0aGlzLm9uVXBkYXRlKCk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgVHJhbnNmb3JtQ2FsbGJhY2sgfSBmcm9tICdzdHJlYW0nO1xuaW1wb3J0IHsgUENNVHJhbnNmb3JtZXIsIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGludGVyZmFjZSBWb2x1bWVUcmFuc2Zvcm1lck9wdGlvbnMgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lck9wdGlvbnMge1xuICB2b2x1bWU/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBWb2x1bWVUcmFuc2Zvcm1lciBleHRlbmRzIFBDTVRyYW5zZm9ybWVyIHtcbiAgcHJpdmF0ZSBfdm9sdW1lID0gMTtcbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM/OiBWb2x1bWVUcmFuc2Zvcm1lck9wdGlvbnMpIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucz8udm9sdW1lID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXRWb2x1bWUob3B0aW9ucy52b2x1bWUpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXQgdm9sdW1lQXBwcm94KCkge1xuICAgIHJldHVybiB0aGlzLl92b2x1bWUgKiAxMDA7XG4gIH1cblxuICBwdWJsaWMgZ2V0IHZvbHVtZSgpIHtcbiAgICByZXR1cm4gTWF0aC5mbG9vcih0aGlzLnZvbHVtZUFwcHJveCk7XG4gIH1cblxuICBwdWJsaWMgc2V0IHZvbHVtZSh2b2x1bWU6IG51bWJlcikge1xuICAgIHRoaXMuc2V0Vm9sdW1lKHZvbHVtZSk7XG4gIH1cblxuICBwdWJsaWMgc2V0Vm9sdW1lKHZvbHVtZTogbnVtYmVyKSB7XG4gICAgaWYgKHR5cGVvZiB2b2x1bWUgIT09ICdudW1iZXInIHx8IGlzTmFOKHZvbHVtZSkpXG4gICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgYEV4cGVjdGVkIHZvbHVtZSBhbW91bnQgdG8gYmUgYSBudW1iZXIsIHJlY2VpdmVkICR7dHlwZW9mIHZvbHVtZX0hYFxuICAgICk7XG4gICAgaWYgKHZvbHVtZSA8IDApIHZvbHVtZSA9IDA7XG4gICAgaWYgKCFpc0Zpbml0ZSh2b2x1bWUpKSB2b2x1bWUgPSAxMDA7XG5cbiAgICB0aGlzLl92b2x1bWUgPSB2b2x1bWUgLyAxMDA7XG5cbiAgICB0aGlzLm9uVXBkYXRlPy4oKTtcblxuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcHVibGljIF90cmFuc2Zvcm0oXG4gIGNodW5rOiBCdWZmZXIsXG4gIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyxcbiAgY2FsbGJhY2s6IFRyYW5zZm9ybUNhbGxiYWNrKVxuICA6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IHRoaXMuX3ZvbHVtZSA9PT0gMSkge1xuICAgICAgdGhpcy5wdXNoKGNodW5rKTtcbiAgICAgIHJldHVybiBjYWxsYmFjaygpO1xuICAgIH1cblxuICAgIGNvbnN0IGxlbiA9IE1hdGguZmxvb3IoY2h1bmsubGVuZ3RoIC8gMikgKiAyO1xuICAgIGNvbnN0IHsgYnl0ZXMgfSA9IHRoaXM7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSArPSBieXRlcykge1xuICAgICAgY29uc3QgaW50ID0gdGhpcy5fcmVhZEludChjaHVuaywgaSk7XG4gICAgICBjb25zdCBhbXAgPSB0aGlzLmNsYW1wKGludCAqIHRoaXMuX3ZvbHVtZSk7XG4gICAgICB0aGlzLl93cml0ZUludChjaHVuaywgYW1wLCBpKTtcbiAgICB9XG5cbiAgICB0aGlzLnB1c2goY2h1bmspO1xuXG4gICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwdWJsaWMgdG9TdHJpbmcoKSB7XG4gICAgcmV0dXJuIGAke3RoaXMudm9sdW1lfSVgO1xuICB9XG59IiwgImltcG9ydCB7IFBDTVRyYW5zZm9ybWVyLCBQQ01UcmFuc2Zvcm1lck9wdGlvbnMgfSBmcm9tICcuLi91dGlscy9QQ01UcmFuc2Zvcm1lcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29tcHJlc3Nvck9wdGlvbnMgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lck9wdGlvbnMge1xuICB0aHJlc2hvbGQ/OiBudW1iZXI7XG4gIHJhdGlvPzogbnVtYmVyO1xuICBhdHRhY2s/OiBudW1iZXI7XG4gIHJlbGVhc2U/OiBudW1iZXI7XG4gIG1ha2V1cEdhaW4/OiBudW1iZXI7XG4gIGtuZWVXaWR0aD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21wcmVzc29yUGFyYW1ldGVycyB7XG4gIHRocmVzaG9sZDogbnVtYmVyO1xuICByYXRpbzogbnVtYmVyO1xuICBhdHRhY2s6IG51bWJlcjtcbiAgcmVsZWFzZTogbnVtYmVyO1xuICBtYWtldXBHYWluOiBudW1iZXI7XG4gIGtuZWVXaWR0aDogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgQ29tcHJlc3NvclRyYW5zZm9ybWVyIGV4dGVuZHMgUENNVHJhbnNmb3JtZXIge1xuICBwcml2YXRlIHRocmVzaG9sZDogbnVtYmVyO1xuICBwcml2YXRlIHJhdGlvOiBudW1iZXI7XG4gIHByaXZhdGUgYXR0YWNrOiBudW1iZXI7XG4gIHByaXZhdGUgcmVsZWFzZTogbnVtYmVyO1xuICBwcml2YXRlIG1ha2V1cEdhaW46IG51bWJlcjtcbiAgcHJpdmF0ZSBrbmVlV2lkdGg6IG51bWJlcjtcbiAgcHJpdmF0ZSBlbnZlbG9wZTogbnVtYmVyID0gMDtcbiAgcHJpdmF0ZSBnYWluUmVkdWN0aW9uOiBudW1iZXIgPSAxO1xuICBwcml2YXRlIHByZXZpb3VzR2FpblJlZHVjdGlvbjogbnVtYmVyID0gMTtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBDb21wcmVzc29yT3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG5cbiAgICB0aGlzLnRocmVzaG9sZCA9IG9wdGlvbnMudGhyZXNob2xkID8/IC0yMDtcbiAgICB0aGlzLnJhdGlvID0gb3B0aW9ucy5yYXRpbyA/PyA0O1xuICAgIHRoaXMuYXR0YWNrID0gb3B0aW9ucy5hdHRhY2sgPz8gMjA7XG4gICAgdGhpcy5yZWxlYXNlID0gb3B0aW9ucy5yZWxlYXNlID8/IDEwMDtcbiAgICB0aGlzLm1ha2V1cEdhaW4gPSBvcHRpb25zLm1ha2V1cEdhaW4gPz8gMDtcbiAgICB0aGlzLmtuZWVXaWR0aCA9IG9wdGlvbnMua25lZVdpZHRoID8/IDY7XG4gICAgdGhpcy5hdHRhY2sgPSBNYXRoLmV4cCgtMSAvICh0aGlzLnNhbXBsZVJhdGUgKiB0aGlzLmF0dGFjayAvIDEwMDApKTtcbiAgICB0aGlzLnJlbGVhc2UgPSBNYXRoLmV4cCgtMSAvICh0aGlzLnNhbXBsZVJhdGUgKiB0aGlzLnJlbGVhc2UgLyAxMDAwKSk7XG4gIH1cblxuICBwcml2YXRlIGxpbmVhclRvRGIobGluZWFyOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHZhbCA9IDIwICogTWF0aC5sb2cxMChNYXRoLm1heChsaW5lYXIsIDFlLTYpKTtcbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgcHJpdmF0ZSBkYlRvTGluZWFyKGRiOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHZhbCA9IE1hdGgucG93KDEwLCBkYiAvIDIwKTtcbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgcHVibGljIHNldFRocmVzaG9sZChkYjogbnVtYmVyKSB7XG4gICAgdGhpcy50aHJlc2hvbGQgPSBNYXRoLm1heCgtMTAwLCBNYXRoLm1pbigwLCBkYikpO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRSYXRpbyhyYXRpbzogbnVtYmVyKSB7XG4gICAgdGhpcy5yYXRpbyA9IE1hdGgubWF4KDEsIHJhdGlvKTtcbiAgICB0aGlzLm9uVXBkYXRlKCk7XG4gIH1cblxuICBwdWJsaWMgc2V0QXR0YWNrKG1zOiBudW1iZXIpIHtcbiAgICB0aGlzLmF0dGFjayA9IE1hdGguZXhwKC0xIC8gKHRoaXMuc2FtcGxlUmF0ZSAqIE1hdGgubWF4KDAuMSwgbXMpIC8gMTAwMCkpO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRSZWxlYXNlKG1zOiBudW1iZXIpIHtcbiAgICB0aGlzLnJlbGVhc2UgPSBNYXRoLmV4cChcbiAgICAgIC0xIC8gKHRoaXMuc2FtcGxlUmF0ZSAqIE1hdGgubWF4KDAuMSwgbXMpIC8gMTAwMClcbiAgICApO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRNYWtldXBHYWluKGRiOiBudW1iZXIpIHtcbiAgICB0aGlzLm1ha2V1cEdhaW4gPSBNYXRoLm1heCgtMjAsIE1hdGgubWluKDIwLCBkYikpO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRLbmVlV2lkdGgoZGI6IG51bWJlcikge1xuICAgIHRoaXMua25lZVdpZHRoID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMjAsIGRiKSk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIHNldENvbXByZXNzb3Iob3B0aW9uczogUGFydGlhbDxDb21wcmVzc29yUGFyYW1ldGVycz4pIHtcbiAgICBpZiAodHlwZW9mIG9wdGlvbnMudGhyZXNob2xkID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXRUaHJlc2hvbGQob3B0aW9ucy50aHJlc2hvbGQpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yYXRpbyA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuc2V0UmF0aW8ob3B0aW9ucy5yYXRpbyk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmF0dGFjayA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuc2V0QXR0YWNrKG9wdGlvbnMuYXR0YWNrKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMucmVsZWFzZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuc2V0UmVsZWFzZShvcHRpb25zLnJlbGVhc2UpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5tYWtldXBHYWluID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXRNYWtldXBHYWluKG9wdGlvbnMubWFrZXVwR2Fpbik7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmtuZWVXaWR0aCA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuc2V0S25lZVdpZHRoKG9wdGlvbnMua25lZVdpZHRoKTtcbiAgICB9XG5cbiAgICB0aGlzLm9uVXBkYXRlKCk7XG5cbiAgICByZXR1cm4gdGhpcy5nZXRQYXJhbWV0ZXJzKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0UGFyYW1ldGVycygpOiBDb21wcmVzc29yUGFyYW1ldGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHRocmVzaG9sZDogdGhpcy50aHJlc2hvbGQsXG4gICAgICByYXRpbzogdGhpcy5yYXRpbyxcbiAgICAgIGF0dGFjazogdGhpcy5hdHRhY2ssXG4gICAgICByZWxlYXNlOiB0aGlzLnJlbGVhc2UsXG4gICAgICBtYWtldXBHYWluOiB0aGlzLm1ha2V1cEdhaW4sXG4gICAgICBrbmVlV2lkdGg6IHRoaXMua25lZVdpZHRoXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgY29tcHV0ZUdhaW5SZWR1Y3Rpb24oaW5wdXRMZXZlbDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBpbnB1dERiID0gdGhpcy5saW5lYXJUb0RiKGlucHV0TGV2ZWwpO1xuXG4gICAgbGV0IGdhaW5SZWR1Y3Rpb25EYiA9IDA7XG5cbiAgICBpZiAoMiAqIChpbnB1dERiIC0gdGhpcy50aHJlc2hvbGQpIDwgLXRoaXMua25lZVdpZHRoKSB7XG4gICAgICBnYWluUmVkdWN0aW9uRGIgPSAwO1xuICAgIH0gZWxzZSBpZiAoMiAqIE1hdGguYWJzKGlucHV0RGIgLSB0aGlzLnRocmVzaG9sZCkgPD0gdGhpcy5rbmVlV2lkdGgpIHtcbiAgICAgIGNvbnN0IHggPSBpbnB1dERiIC0gdGhpcy50aHJlc2hvbGQgKyB0aGlzLmtuZWVXaWR0aCAvIDI7XG4gICAgICBnYWluUmVkdWN0aW9uRGIgPVxuICAgICAgKDEgLyB0aGlzLnJhdGlvIC0gMSkgKiBNYXRoLnBvdyh4LCAyKSAvICgyICogdGhpcy5rbmVlV2lkdGgpO1xuICAgIH0gZWxzZSB7XG4gICAgICBnYWluUmVkdWN0aW9uRGIgPSAoaW5wdXREYiAtIHRoaXMudGhyZXNob2xkKSAqICgxIC0gMSAvIHRoaXMucmF0aW8pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGlzLmRiVG9MaW5lYXIoLWdhaW5SZWR1Y3Rpb25EYiArIHRoaXMubWFrZXVwR2Fpbik7XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NTYW1wbGUoaW5wdXQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHJldHVybiBpbnB1dDtcblxuICAgIGNvbnN0IGlucHV0RmxvYXQgPSBpbnB1dCAvIHRoaXMuZXh0cmVtdW07XG5cbiAgICBjb25zdCBpbnB1dExldmVsID0gTWF0aC5hYnMoaW5wdXRGbG9hdCk7XG4gICAgY29uc3QgY29lZmYgPSBpbnB1dExldmVsID4gdGhpcy5lbnZlbG9wZSA/IHRoaXMuYXR0YWNrIDogdGhpcy5yZWxlYXNlO1xuICAgIHRoaXMuZW52ZWxvcGUgPSBjb2VmZiAqIHRoaXMuZW52ZWxvcGUgKyAoMSAtIGNvZWZmKSAqIGlucHV0TGV2ZWw7XG5cbiAgICBjb25zdCB0YXJnZXRHYWluUmVkdWN0aW9uID0gdGhpcy5jb21wdXRlR2FpblJlZHVjdGlvbih0aGlzLmVudmVsb3BlKTtcblxuICAgIHRoaXMuZ2FpblJlZHVjdGlvbiA9IE1hdGgubWluKFxuICAgICAgdGhpcy5wcmV2aW91c0dhaW5SZWR1Y3Rpb24gKiB0aGlzLmF0dGFjayArXG4gICAgICB0YXJnZXRHYWluUmVkdWN0aW9uICogKDEgLSB0aGlzLmF0dGFjayksXG4gICAgICB0YXJnZXRHYWluUmVkdWN0aW9uXG4gICAgKTtcbiAgICB0aGlzLnByZXZpb3VzR2FpblJlZHVjdGlvbiA9IHRoaXMuZ2FpblJlZHVjdGlvbjtcblxuICAgIGNvbnN0IG91dHB1dEZsb2F0ID0gaW5wdXRGbG9hdCAqIHRoaXMuZ2FpblJlZHVjdGlvbjtcblxuICAgIHJldHVybiB0aGlzLmNsYW1wKE1hdGguZmxvb3Iob3V0cHV0RmxvYXQgKiB0aGlzLmV4dHJlbXVtKSk7XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgX3RyYW5zZm9ybShcbiAgY2h1bms6IEJ1ZmZlcixcbiAgZW5jb2Rpbmc6IEJ1ZmZlckVuY29kaW5nLFxuICBjYWxsYmFjazogKGVycm9yPzogRXJyb3IgfCBudWxsLCBkYXRhPzogQnVmZmVyKSA9PiB2b2lkKVxuICA6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkKSB7XG4gICAgICBjYWxsYmFjayhudWxsLCBjaHVuayk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0ID0gQnVmZmVyLmFsbG9jKGNodW5rLmxlbmd0aCk7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNodW5rLmxlbmd0aDsgaSArPSB0aGlzLmJ5dGVzKSB7XG4gICAgICBjb25zdCBzYW1wbGUgPSB0aGlzLl9yZWFkSW50KGNodW5rLCBpKTtcbiAgICAgIGNvbnN0IHByb2Nlc3NlZCA9IHRoaXMucHJvY2Vzc1NhbXBsZShzYW1wbGUpO1xuICAgICAgdGhpcy5fd3JpdGVJbnQob3V0cHV0LCBwcm9jZXNzZWQsIGkpO1xuICAgIH1cblxuICAgIGNhbGxiYWNrKG51bGwsIG91dHB1dCk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgUENNVHJhbnNmb3JtZXIsIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCB7IEV2ZW50RW1pdHRlciB9IGZyb20gJ2V2ZW50cyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUENNU2Vla2VyT3B0aW9ucyBleHRlbmRzIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB7XG4gIHRvdGFsRHVyYXRpb246IG51bWJlcjtcbiAgY2hhbm5lbHM6IG51bWJlcjtcbiAgc2Vla1RhcmdldD86IG51bWJlciB8IG51bGw7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2Vla2VyUGFyYW1ldGVycyB7XG4gIGN1cnJlbnRQb3NpdGlvbjogbnVtYmVyO1xuICBzZWVrVGFyZ2V0OiBudW1iZXIgfCBudWxsO1xuICB0b3RhbER1cmF0aW9uOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2Vla0V2ZW50IHtcbiAgcG9zaXRpb246IG51bWJlcjtcbiAgc2FtcGxlOiBudW1iZXI7XG4gIGJ5dGVQb3NpdGlvbjogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgUENNU2Vla2VyVHJhbnNmb3JtZXIgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lciB7XG4gIHByaXZhdGUgdG90YWxEdXJhdGlvbjogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGNoYW5uZWxzOiBudW1iZXI7XG4gIHByaXZhdGUgYnl0ZXNQZXJGcmFtZSE6IG51bWJlcjtcbiAgcHJpdmF0ZSBjdXJyZW50UG9zaXRpb24gPSAwO1xuICBwcml2YXRlIHNlZWtUYXJnZXQ6IG51bWJlciB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGJ1ZmZlcjogQnVmZmVyID0gQnVmZmVyLmFsbG9jKDApO1xuICBwdWJsaWMgcmVhZG9ubHkgZXZlbnRzID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihcbiAgb3B0aW9uczogUENNU2Vla2VyT3B0aW9ucyA9IHtcbiAgICBjaGFubmVsczogMixcbiAgICB0b3RhbER1cmF0aW9uOiAwXG4gIH0pXG4gIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIGlmIChvcHRpb25zLnRvdGFsRHVyYXRpb24gPT0gbnVsbCB8fCBvcHRpb25zLnRvdGFsRHVyYXRpb24gPCAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RvdGFsRHVyYXRpb24gbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICAgIH1cblxuICAgIGlmICghb3B0aW9ucy5jaGFubmVscyB8fCBvcHRpb25zLmNoYW5uZWxzIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignY2hhbm5lbHMgbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICAgIH1cblxuICAgIHRoaXMudG90YWxEdXJhdGlvbiA9IG9wdGlvbnMudG90YWxEdXJhdGlvbjtcbiAgICB0aGlzLmNoYW5uZWxzID0gb3B0aW9ucy5jaGFubmVscztcblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5zZWVrVGFyZ2V0ID09PSAnbnVtYmVyJyAmJiBvcHRpb25zLnNlZWtUYXJnZXQgPiAwKSB7XG4gICAgICB0aGlzLnNlZWtUYXJnZXQgPSBvcHRpb25zLnNlZWtUYXJnZXQ7XG4gICAgfVxuXG4gICAgdGhpcy51cGRhdGVEZXBlbmRlbnRWYWx1ZXMoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRQYXJhbWV0ZXJzKCk6IFNlZWtlclBhcmFtZXRlcnMge1xuICAgIHJldHVybiB7XG4gICAgICBjdXJyZW50UG9zaXRpb246IHRoaXMuY3VycmVudFBvc2l0aW9uLFxuICAgICAgc2Vla1RhcmdldDogdGhpcy5zZWVrVGFyZ2V0LFxuICAgICAgdG90YWxEdXJhdGlvbjogdGhpcy50b3RhbER1cmF0aW9uXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgdXBkYXRlRGVwZW5kZW50VmFsdWVzKCk6IHZvaWQge1xuICAgIHRoaXMuYnl0ZXNQZXJGcmFtZSA9IHRoaXMuYnl0ZXMgKiB0aGlzLmNoYW5uZWxzO1xuXG4gICAgaWYgKHRoaXMuY3VycmVudFBvc2l0aW9uID4gMCkge1xuICAgICAgY29uc3QgY3VycmVudE1zID0gdGhpcy5jdXJyZW50UG9zaXRpb24gLyAodGhpcy5zYW1wbGVSYXRlIC8gMTAwMCk7XG4gICAgICB0aGlzLmN1cnJlbnRQb3NpdGlvbiA9IE1hdGguZmxvb3IoY3VycmVudE1zIC8gMTAwMCAqIHRoaXMuc2FtcGxlUmF0ZSk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2Vla1RhcmdldCAhPT0gbnVsbCkge1xuICAgICAgY29uc3Qgc2Vla01zID0gdGhpcy5zZWVrVGFyZ2V0IC8gKHRoaXMuc2FtcGxlUmF0ZSAvIDEwMDApO1xuICAgICAgdGhpcy5zZWVrVGFyZ2V0ID0gTWF0aC5mbG9vcihzZWVrTXMgLyAxMDAwICogdGhpcy5zYW1wbGVSYXRlKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIGJ5dGUgcG9zaXRpb24gZnJvbSBzYW1wbGUgcG9zaXRpb25cbiAgICogQHBhcmFtIHNhbXBsZVBvc2l0aW9uIFBvc2l0aW9uIGluIHNhbXBsZXNcbiAgICogQHJldHVybnMgUG9zaXRpb24gaW4gYnl0ZXNcbiAgICovXG4gIHByaXZhdGUgc2FtcGxlVG9CeXRlUG9zaXRpb24oc2FtcGxlUG9zaXRpb246IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHNhbXBsZVBvc2l0aW9uICogdGhpcy5ieXRlc1BlckZyYW1lO1xuICB9XG5cbiAgcHVibGljIHNldFRvdGFsRHVyYXRpb24oZHVyYXRpb246IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChkdXJhdGlvbiA8PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3RvdGFsRHVyYXRpb24gbXVzdCBiZSBhIHBvc2l0aXZlIG51bWJlcicpO1xuICAgIH1cblxuICAgIHRoaXMudG90YWxEdXJhdGlvbiA9IGR1cmF0aW9uO1xuICAgIHRoaXMudXBkYXRlRGVwZW5kZW50VmFsdWVzKCk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIHNldFNhbXBsZVJhdGUocmF0ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgc3VwZXIuc2V0U2FtcGxlUmF0ZShyYXRlKTtcbiAgICB0aGlzLnVwZGF0ZURlcGVuZGVudFZhbHVlcygpO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZWVrIHRvIGEgc3BlY2lmaWMgcG9zaXRpb24gaW4gbWlsbGlzZWNvbmRzXG4gICAqIEBwYXJhbSBtcyBQb3NpdGlvbiBpbiBtaWxsaXNlY29uZHMgKG5lZ2F0aXZlIHZhbHVlcyBzZWVrIGZyb20gZW5kKVxuICAgKiBAcmV0dXJucyBBY3R1YWwgcG9zaXRpb24gaW4gbWlsbGlzZWNvbmRzIGFmdGVyIHNlZWtpbmdcbiAgICovXG4gIHB1YmxpYyBzZWVrKG1zOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLnRvdGFsRHVyYXRpb24gPT09IDApIHJldHVybiAwO1xuXG4gICAgaWYgKG1zIDwgMCkge1xuICAgICAgbXMgPSBNYXRoLm1heCgwLCB0aGlzLnRvdGFsRHVyYXRpb24gKyBtcyk7XG4gICAgfVxuXG4gICAgbXMgPSBNYXRoLm1heCgwLCBNYXRoLm1pbih0aGlzLnRvdGFsRHVyYXRpb24sIG1zKSk7XG4gICAgY29uc3QgdGFyZ2V0U2FtcGxlID0gTWF0aC5mbG9vcihtcyAvIDEwMDAgKiB0aGlzLnNhbXBsZVJhdGUpO1xuXG4gICAgaWYgKHRhcmdldFNhbXBsZSA8IHRoaXMuY3VycmVudFBvc2l0aW9uKSB7XG4gICAgICB0aGlzLmJ1ZmZlciA9IEJ1ZmZlci5hbGxvYygwKTtcblxuICAgICAgY29uc3QgYnl0ZVBvc2l0aW9uID0gdGhpcy5zYW1wbGVUb0J5dGVQb3NpdGlvbih0YXJnZXRTYW1wbGUpO1xuXG4gICAgICB0aGlzLmV2ZW50cy5lbWl0KCdzZWVrJywge1xuICAgICAgICBwb3NpdGlvbjogbXMsXG4gICAgICAgIHNhbXBsZTogdGFyZ2V0U2FtcGxlLFxuICAgICAgICBieXRlUG9zaXRpb246IGJ5dGVQb3NpdGlvblxuICAgICAgfSBhcyBTZWVrRXZlbnQpO1xuICAgIH1cblxuICAgIHRoaXMuc2Vla1RhcmdldCA9IHRhcmdldFNhbXBsZTtcbiAgICByZXR1cm4gdGFyZ2V0U2FtcGxlIC8gdGhpcy5zYW1wbGVSYXRlICogMTAwMDtcbiAgfVxuXG4gIHB1YmxpYyBnZXRQb3NpdGlvbigpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnRQb3NpdGlvbiAvIHRoaXMuc2FtcGxlUmF0ZSAqIDEwMDA7XG4gIH1cblxuICBwcml2YXRlIGhhbmRsZVNlZWsoY2h1bms6IEJ1ZmZlcik6IEJ1ZmZlciB7XG4gICAgaWYgKHRoaXMuc2Vla1RhcmdldCA9PT0gbnVsbCkgcmV0dXJuIGNodW5rO1xuXG4gICAgY29uc3QgY2h1bmtTdGFydFNhbXBsZSA9IHRoaXMuY3VycmVudFBvc2l0aW9uO1xuICAgIGNvbnN0IGNodW5rU2FtcGxlcyA9IE1hdGguZmxvb3IoY2h1bmsubGVuZ3RoIC8gdGhpcy5ieXRlc1BlckZyYW1lKTtcbiAgICBjb25zdCBjaHVua0VuZFNhbXBsZSA9IGNodW5rU3RhcnRTYW1wbGUgKyBjaHVua1NhbXBsZXM7XG5cbiAgICBpZiAodGhpcy5zZWVrVGFyZ2V0ID49IGNodW5rRW5kU2FtcGxlKSB7XG4gICAgICB0aGlzLmN1cnJlbnRQb3NpdGlvbiArPSBjaHVua1NhbXBsZXM7XG4gICAgICByZXR1cm4gQnVmZmVyLmFsbG9jKDApO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnNlZWtUYXJnZXQgPj0gY2h1bmtTdGFydFNhbXBsZSkge1xuICAgICAgY29uc3Qgb2Zmc2V0U2FtcGxlcyA9IHRoaXMuc2Vla1RhcmdldCAtIGNodW5rU3RhcnRTYW1wbGU7XG4gICAgICBjb25zdCBvZmZzZXRCeXRlcyA9IG9mZnNldFNhbXBsZXMgKiB0aGlzLmJ5dGVzUGVyRnJhbWU7XG4gICAgICB0aGlzLmN1cnJlbnRQb3NpdGlvbiA9IHRoaXMuc2Vla1RhcmdldDtcbiAgICAgIHRoaXMuc2Vla1RhcmdldCA9IG51bGw7XG4gICAgICByZXR1cm4gY2h1bmsuc3ViYXJyYXkob2Zmc2V0Qnl0ZXMpO1xuICAgIH1cblxuICAgIHRoaXMuY3VycmVudFBvc2l0aW9uID0gdGhpcy5zZWVrVGFyZ2V0O1xuICAgIHRoaXMuc2Vla1RhcmdldCA9IG51bGw7XG4gICAgcmV0dXJuIGNodW5rO1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIF90cmFuc2Zvcm0oXG4gIGNodW5rOiBCdWZmZXIsXG4gIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyxcbiAgY2FsbGJhY2s6IChlcnJvcj86IEVycm9yIHwgbnVsbCwgZGF0YT86IEJ1ZmZlcikgPT4gdm9pZClcbiAgOiB2b2lkIHtcbiAgICB0cnkge1xuICAgICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgdGhpcy50b3RhbER1cmF0aW9uID09PSAwKSB7XG4gICAgICAgIGNhbGxiYWNrKG51bGwsIGNodW5rKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBjb21iaW5lZEJ1ZmZlciA9IEJ1ZmZlci5jb25jYXQoW3RoaXMuYnVmZmVyLCBjaHVua10pO1xuICAgICAgY29uc3QgZnJhbWVDb3VudCA9IE1hdGguZmxvb3IoY29tYmluZWRCdWZmZXIubGVuZ3RoIC8gdGhpcy5ieXRlc1BlckZyYW1lKTtcbiAgICAgIGNvbnN0IHByb2Nlc3NhYmxlQnl0ZXMgPSBmcmFtZUNvdW50ICogdGhpcy5ieXRlc1BlckZyYW1lO1xuXG4gICAgICB0aGlzLmJ1ZmZlciA9IGNvbWJpbmVkQnVmZmVyLnN1YmFycmF5KHByb2Nlc3NhYmxlQnl0ZXMpO1xuXG4gICAgICBsZXQgcHJvY2Vzc0J1ZmZlciA9IGNvbWJpbmVkQnVmZmVyLnN1YmFycmF5KDAsIHByb2Nlc3NhYmxlQnl0ZXMpO1xuXG4gICAgICBpZiAodGhpcy5zZWVrVGFyZ2V0ICE9PSBudWxsKSB7XG4gICAgICAgIHByb2Nlc3NCdWZmZXIgPSB0aGlzLmhhbmRsZVNlZWsocHJvY2Vzc0J1ZmZlcik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmN1cnJlbnRQb3NpdGlvbiArPSBmcmFtZUNvdW50O1xuICAgICAgfVxuXG4gICAgICBjYWxsYmFjayhudWxsLCBwcm9jZXNzQnVmZmVyKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY2FsbGJhY2soZXJyb3IgYXMgRXJyb3IpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZSBfZmx1c2goXG4gIGNhbGxiYWNrOiAoZXJyb3I/OiBFcnJvciB8IG51bGwsIGRhdGE/OiBCdWZmZXIpID0+IHZvaWQpXG4gIDogdm9pZCB7XG4gICAgaWYgKHRoaXMuYnVmZmVyLmxlbmd0aCA+PSB0aGlzLmJ5dGVzUGVyRnJhbWUpIHtcbiAgICAgIGNvbnN0IGZyYW1lQ291bnQgPSBNYXRoLmZsb29yKHRoaXMuYnVmZmVyLmxlbmd0aCAvIHRoaXMuYnl0ZXNQZXJGcmFtZSk7XG4gICAgICBjb25zdCBwcm9jZXNzYWJsZUJ5dGVzID0gZnJhbWVDb3VudCAqIHRoaXMuYnl0ZXNQZXJGcmFtZTtcbiAgICAgIGNhbGxiYWNrKG51bGwsIHRoaXMuYnVmZmVyLnN1YmFycmF5KDAsIHByb2Nlc3NhYmxlQnl0ZXMpKTtcbiAgICB9XG5cbiAgICBjYWxsYmFjaygpO1xuICB9XG59IiwgImltcG9ydCB7IFBDTVRyYW5zZm9ybWVyLCBQQ01UcmFuc2Zvcm1lck9wdGlvbnMgfSBmcm9tICcuLi91dGlscyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmV2ZXJiT3B0aW9ucyBleHRlbmRzIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB7XG4gIHJvb21TaXplPzogbnVtYmVyO1xuICBkYW1waW5nPzogbnVtYmVyO1xuICB3ZXRMZXZlbD86IG51bWJlcjtcbiAgZHJ5TGV2ZWw/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUmV2ZXJiUGFyYW1ldGVycyB7XG4gIHJvb21TaXplOiBudW1iZXI7XG4gIGRhbXBpbmc6IG51bWJlcjtcbiAgd2V0TGV2ZWw6IG51bWJlcjtcbiAgZHJ5TGV2ZWw6IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIFJldmVyYlRyYW5zZm9ybWVyIGV4dGVuZHMgUENNVHJhbnNmb3JtZXIge1xuICBwcml2YXRlIHJvb21TaXplOiBudW1iZXI7XG4gIHByaXZhdGUgZGFtcGluZzogbnVtYmVyO1xuICBwcml2YXRlIHdldExldmVsOiBudW1iZXI7XG4gIHByaXZhdGUgZHJ5TGV2ZWw6IG51bWJlcjtcblxuICBwcml2YXRlIHJlYWRvbmx5IGRlbGF5TGluZXM6IEZsb2F0MzJBcnJheVtdO1xuICBwcml2YXRlIHJlYWRvbmx5IGRlbGF5TGluZUxlbmd0aDogbnVtYmVyO1xuICBwcml2YXRlIGRlbGF5SW5kaWNlczogbnVtYmVyW107XG4gIHByaXZhdGUgcmVhZG9ubHkgbnVtRGVsYXlMaW5lcyA9IDg7XG4gIHByaXZhdGUgcmVhZG9ubHkgZmVlZGJhY2s6IG51bWJlciA9IDAuODQ7XG5cbiAgY29uc3RydWN0b3Iob3B0aW9uczogUmV2ZXJiT3B0aW9ucyA9IHt9KSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG5cbiAgICB0aGlzLnJvb21TaXplID0gb3B0aW9ucy5yb29tU2l6ZSA/PyAwLjU7XG4gICAgdGhpcy5kYW1waW5nID0gb3B0aW9ucy5kYW1waW5nID8/IDAuNTtcbiAgICB0aGlzLndldExldmVsID0gb3B0aW9ucy53ZXRMZXZlbCA/PyAwLjM7XG4gICAgdGhpcy5kcnlMZXZlbCA9IG9wdGlvbnMuZHJ5TGV2ZWwgPz8gMC43O1xuXG4gICAgdGhpcy5kZWxheUxpbmVMZW5ndGggPSBNYXRoLmZsb29yKHRoaXMuc2FtcGxlUmF0ZSAqIDAuMDUpO1xuICAgIHRoaXMuZGVsYXlMaW5lcyA9IEFycmF5LmZyb20oXG4gICAgICB7IGxlbmd0aDogdGhpcy5udW1EZWxheUxpbmVzIH0sXG4gICAgICAoKSA9PiBuZXcgRmxvYXQzMkFycmF5KHRoaXMuZGVsYXlMaW5lTGVuZ3RoKVxuICAgICk7XG4gICAgdGhpcy5kZWxheUluZGljZXMgPSBBcnJheSh0aGlzLm51bURlbGF5TGluZXMpLmZpbGwoMCk7XG4gIH1cblxuICBwdWJsaWMgc2V0Um9vbVNpemUoc2l6ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5yb29tU2l6ZSA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIHNpemUpKTtcbiAgICB0aGlzLm9uVXBkYXRlKCk7XG4gIH1cblxuICBwdWJsaWMgc2V0RGFtcGluZyhkYW1waW5nOiBudW1iZXIpIHtcbiAgICB0aGlzLmRhbXBpbmcgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBkYW1waW5nKSk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIHNldFdldExldmVsKGxldmVsOiBudW1iZXIpIHtcbiAgICB0aGlzLndldExldmVsID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgbGV2ZWwpKTtcbiAgICB0aGlzLm9uVXBkYXRlKCk7XG4gIH1cblxuICBwdWJsaWMgc2V0RHJ5TGV2ZWwobGV2ZWw6IG51bWJlcikge1xuICAgIHRoaXMuZHJ5TGV2ZWwgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBsZXZlbCkpO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRSZXZlcmIob3B0aW9uczogUGFydGlhbDxSZXZlcmJQYXJhbWV0ZXJzPikge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yb29tU2l6ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuc2V0Um9vbVNpemUob3B0aW9ucy5yb29tU2l6ZSk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmRhbXBpbmcgPT09ICdudW1iZXInKSB7XG4gICAgICB0aGlzLnNldERhbXBpbmcob3B0aW9ucy5kYW1waW5nKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMud2V0TGV2ZWwgPT09ICdudW1iZXInKSB7XG4gICAgICB0aGlzLnNldFdldExldmVsKG9wdGlvbnMud2V0TGV2ZWwpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5kcnlMZXZlbCA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuc2V0RHJ5TGV2ZWwob3B0aW9ucy5kcnlMZXZlbCk7XG4gICAgfVxuXG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuXG4gICAgcmV0dXJuIHRoaXMuZ2V0UGFyYW1ldGVycygpO1xuICB9XG5cbiAgcHVibGljIGdldFBhcmFtZXRlcnMoKTogUmV2ZXJiUGFyYW1ldGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIHJvb21TaXplOiB0aGlzLnJvb21TaXplLFxuICAgICAgZGFtcGluZzogdGhpcy5kYW1waW5nLFxuICAgICAgd2V0TGV2ZWw6IHRoaXMud2V0TGV2ZWwsXG4gICAgICBkcnlMZXZlbDogdGhpcy5kcnlMZXZlbFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIHByb2Nlc3NTYW1wbGUoaW5wdXQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHJldHVybiBpbnB1dDtcblxuICAgIGNvbnN0IGlucHV0RmxvYXQgPSBpbnB1dCAvIHRoaXMuZXh0cmVtdW07XG4gICAgbGV0IHdldCA9IDA7XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMubnVtRGVsYXlMaW5lczsgaSsrKSB7XG4gICAgICBjb25zdCBkZWxheUxpbmUgPSB0aGlzLmRlbGF5TGluZXNbaV07XG4gICAgICBjb25zdCBkZWxheUluZGV4ID0gdGhpcy5kZWxheUluZGljZXNbaV07XG5cbiAgICAgIGNvbnN0IGRlbGF5ZWQgPSBkZWxheUxpbmVbZGVsYXlJbmRleF07XG5cbiAgICAgIGNvbnN0IHByb2Nlc3NlZCA9IGRlbGF5ZWQgKiB0aGlzLnJvb21TaXplICogKDEgLSB0aGlzLmRhbXBpbmcpO1xuXG4gICAgICBkZWxheUxpbmVbZGVsYXlJbmRleF0gPSBpbnB1dEZsb2F0ICsgcHJvY2Vzc2VkICogdGhpcy5mZWVkYmFjaztcblxuICAgICAgdGhpcy5kZWxheUluZGljZXNbaV0gPSAoZGVsYXlJbmRleCArIDEpICUgdGhpcy5kZWxheUxpbmVMZW5ndGg7XG5cbiAgICAgIHdldCArPSBwcm9jZXNzZWQ7XG4gICAgfVxuXG4gICAgY29uc3Qgb3V0cHV0ID1cbiAgICBpbnB1dEZsb2F0ICogdGhpcy5kcnlMZXZlbCArIHdldCAqIHRoaXMud2V0TGV2ZWwgLyB0aGlzLm51bURlbGF5TGluZXM7XG5cbiAgICByZXR1cm4gdGhpcy5jbGFtcChNYXRoLmZsb29yKG91dHB1dCAqIHRoaXMuZXh0cmVtdW0pKTtcbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZSBfdHJhbnNmb3JtKFxuICBjaHVuazogQnVmZmVyLFxuICBlbmNvZGluZzogQnVmZmVyRW5jb2RpbmcsXG4gIGNhbGxiYWNrOiAoZXJyb3I/OiBFcnJvciB8IG51bGwsIGRhdGE/OiBCdWZmZXIpID0+IHZvaWQpXG4gIDogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIGNhbGxiYWNrKG51bGwsIGNodW5rKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXQgPSBCdWZmZXIuYWxsb2MoY2h1bmsubGVuZ3RoKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2h1bmsubGVuZ3RoOyBpICs9IHRoaXMuYnl0ZXMpIHtcbiAgICAgIGNvbnN0IHNhbXBsZSA9IHRoaXMuX3JlYWRJbnQoY2h1bmssIGkpO1xuICAgICAgY29uc3QgcHJvY2Vzc2VkID0gdGhpcy5wcm9jZXNzU2FtcGxlKHNhbXBsZSk7XG4gICAgICB0aGlzLl93cml0ZUludChvdXRwdXQsIHByb2Nlc3NlZCwgaSk7XG4gICAgfVxuXG4gICAgY2FsbGJhY2sobnVsbCwgb3V0cHV0KTtcbiAgfVxufSIsICJpbXBvcnQgeyB0eXBlIFJlYWRhYmxlLCBwaXBlbGluZSB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBFcXVhbGl6ZXJTdHJlYW0sIEVxdWFsaXplclN0cmVhbU9wdGlvbnMgfSBmcm9tICcuL2VxdWFsaXplcic7XG5pbXBvcnQge1xuICBBdWRpb0ZpbHRlcixcbiAgQ29tcHJlc3Nvck9wdGlvbnMsXG4gIENvbXByZXNzb3JUcmFuc2Zvcm1lcixcbiAgUENNRmlsdGVyZXJPcHRpb25zLFxuICBQQ01SZXNhbXBsZXIsXG4gIFBDTVJlc2FtcGxlck9wdGlvbnMsXG4gIFBDTVNlZWtlck9wdGlvbnMsXG4gIFBDTVNlZWtlclRyYW5zZm9ybWVyLFxuICBSZXZlcmJPcHRpb25zLFxuICBSZXZlcmJUcmFuc2Zvcm1lciB9IGZyb21cbicuL2F1ZGlvJztcbmltcG9ydCB7IEJpcXVhZFN0cmVhbSwgQmlxdWFkU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4vYmlxdWFkJztcbmltcG9ydCB7XG4gIFZvbHVtZVRyYW5zZm9ybWVyLFxuICBWb2x1bWVUcmFuc2Zvcm1lck9wdGlvbnMgfSBmcm9tXG4nLi9hdWRpby9Wb2x1bWVUcmFuc2Zvcm1lcic7XG5cbmV4cG9ydCBpbnRlcmZhY2UgRFNQRmlsdGVyc1ByZXNldCB7XG4gIGVxdWFsaXplcj86IEVxdWFsaXplclN0cmVhbU9wdGlvbnM7XG4gIGRzcD86IFBDTUZpbHRlcmVyT3B0aW9ucztcbiAgYmlxdWFkPzogQmlxdWFkU3RyZWFtT3B0aW9ucztcbiAgdm9sdW1lPzogVm9sdW1lVHJhbnNmb3JtZXJPcHRpb25zO1xuICByZXNhbXBsZXI/OiBQQ01SZXNhbXBsZXJPcHRpb25zO1xuICBjb21wcmVzc29yPzogQ29tcHJlc3Nvck9wdGlvbnM7XG4gIHNlZWtlcj86IFBDTVNlZWtlck9wdGlvbnM7XG4gIHJldmVyYj86IFJldmVyYk9wdGlvbnM7XG59XG5cbmV4cG9ydCBjbGFzcyBGaWx0ZXJzQ2hhaW4ge1xuICBwdWJsaWMgZXF1YWxpemVyOiBFcXVhbGl6ZXJTdHJlYW0gfCBudWxsID0gbnVsbDtcbiAgcHVibGljIGZpbHRlcnM6IEF1ZGlvRmlsdGVyIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyBiaXF1YWQ6IEJpcXVhZFN0cmVhbSB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgdm9sdW1lOiBWb2x1bWVUcmFuc2Zvcm1lciB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgcmVzYW1wbGVyOiBQQ01SZXNhbXBsZXIgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIGNvbXByZXNzb3I6IENvbXByZXNzb3JUcmFuc2Zvcm1lciB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgc2Vla2VyOiBQQ01TZWVrZXJUcmFuc2Zvcm1lciB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgcmV2ZXJiOiBSZXZlcmJUcmFuc2Zvcm1lciB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgZGVzdGluYXRpb246IFJlYWRhYmxlIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyBzb3VyY2U6IFJlYWRhYmxlIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyBvblVwZGF0ZTogKCkgPT4gdW5rbm93biA9ICgpID0+IG51bGw7XG4gIHB1YmxpYyBvbkVycm9yOiAoZXJyOiBFcnJvcikgPT4gdW5rbm93biA9ICgpID0+IG51bGw7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKHB1YmxpYyBwcmVzZXRzOiBEU1BGaWx0ZXJzUHJlc2V0ID0ge30pIHt9XG5cbiAgcHVibGljIGNyZWF0ZShzcmM6IFJlYWRhYmxlLCBwcmVzZXRzOiBEU1BGaWx0ZXJzUHJlc2V0ID0gdGhpcy5wcmVzZXRzKSB7XG4gICAgdGhpcy5kZXN0cm95KCk7XG5cbiAgICB0aGlzLnNvdXJjZSA9IHNyYztcblxuICAgIGNvbnN0IHJlc2FtcGxlciA9ICFwcmVzZXRzLnJlc2FtcGxlcj8uZGlzYWJsZWQgP1xuICAgIG5ldyBQQ01SZXNhbXBsZXIocHJlc2V0cy5yZXNhbXBsZXIpIDpcbiAgICBudWxsO1xuXG4gICAgY29uc3QgZXF1YWxpemVyU3RyZWFtID0gIXByZXNldHMuZXF1YWxpemVyPy5kaXNhYmxlZCA/XG4gICAgbmV3IEVxdWFsaXplclN0cmVhbShwcmVzZXRzLmVxdWFsaXplcikgOlxuICAgIG51bGw7XG5cbiAgICBjb25zdCBkc3BTdHJlYW0gPSAhcHJlc2V0cy5kc3A/LmRpc2FibGVkID9cbiAgICBuZXcgQXVkaW9GaWx0ZXIocHJlc2V0cy5kc3ApIDpcbiAgICBudWxsO1xuXG4gICAgY29uc3QgYmlxdWFkU3RyZWFtID0gIXByZXNldHMuYmlxdWFkPy5kaXNhYmxlZCA/XG4gICAgbmV3IEJpcXVhZFN0cmVhbShwcmVzZXRzLmJpcXVhZCkgOlxuICAgIG51bGw7XG5cbiAgICBjb25zdCB2b2x1bWVUcmFuc2Zvcm1lciA9ICFwcmVzZXRzLnZvbHVtZT8uZGlzYWJsZWQgP1xuICAgIG5ldyBWb2x1bWVUcmFuc2Zvcm1lcihwcmVzZXRzLnZvbHVtZSkgOlxuICAgIG51bGw7XG5cbiAgICBjb25zdCBjb21wcmVzc29yID0gIXByZXNldHMuY29tcHJlc3Nvcj8uZGlzYWJsZWQgP1xuICAgIG5ldyBDb21wcmVzc29yVHJhbnNmb3JtZXIocHJlc2V0cy5jb21wcmVzc29yKSA6XG4gICAgbnVsbDtcblxuICAgIGNvbnN0IHNlZWtlciA9ICFwcmVzZXRzLnNlZWtlcj8uZGlzYWJsZWQgP1xuICAgIG5ldyBQQ01TZWVrZXJUcmFuc2Zvcm1lcihwcmVzZXRzLnNlZWtlcikgOlxuICAgIG51bGw7XG5cbiAgICBjb25zdCByZXZlcmIgPSAhcHJlc2V0cy5yZXZlcmI/LmRpc2FibGVkID9cbiAgICBuZXcgUmV2ZXJiVHJhbnNmb3JtZXIocHJlc2V0cy5yZXZlcmIpIDpcbiAgICBudWxsO1xuXG4gICAgdGhpcy5yZXNhbXBsZXIgPSByZXNhbXBsZXI7XG4gICAgdGhpcy5lcXVhbGl6ZXIgPSBlcXVhbGl6ZXJTdHJlYW07XG4gICAgdGhpcy5maWx0ZXJzID0gZHNwU3RyZWFtO1xuICAgIHRoaXMuYmlxdWFkID0gYmlxdWFkU3RyZWFtO1xuICAgIHRoaXMudm9sdW1lID0gdm9sdW1lVHJhbnNmb3JtZXI7XG4gICAgdGhpcy5jb21wcmVzc29yID0gY29tcHJlc3NvcjtcbiAgICB0aGlzLnNlZWtlciA9IHNlZWtlcjtcbiAgICB0aGlzLnJldmVyYiA9IHJldmVyYjtcblxuICAgIC8vIHVwZGF0ZSBsaXN0ZW5lcnNcbiAgICBpZiAocmVzYW1wbGVyKSByZXNhbXBsZXIub25VcGRhdGUgPSB0aGlzLm9uVXBkYXRlO1xuICAgIGlmIChlcXVhbGl6ZXJTdHJlYW0pIGVxdWFsaXplclN0cmVhbS5vblVwZGF0ZSA9IHRoaXMub25VcGRhdGU7XG4gICAgaWYgKGRzcFN0cmVhbSkgZHNwU3RyZWFtLm9uVXBkYXRlID0gdGhpcy5vblVwZGF0ZTtcbiAgICBpZiAoYmlxdWFkU3RyZWFtKSBiaXF1YWRTdHJlYW0ub25VcGRhdGUgPSB0aGlzLm9uVXBkYXRlO1xuICAgIGlmICh2b2x1bWVUcmFuc2Zvcm1lcikgdm9sdW1lVHJhbnNmb3JtZXIub25VcGRhdGUgPSB0aGlzLm9uVXBkYXRlO1xuICAgIGlmIChjb21wcmVzc29yKSBjb21wcmVzc29yLm9uVXBkYXRlID0gdGhpcy5vblVwZGF0ZTtcbiAgICBpZiAoc2Vla2VyKSBzZWVrZXIub25VcGRhdGUgPSB0aGlzLm9uVXBkYXRlO1xuICAgIGlmIChyZXZlcmIpIHJldmVyYi5vblVwZGF0ZSA9IHRoaXMub25VcGRhdGU7XG5cbiAgICBjb25zdCBjaGFpbnMgPSBbXG4gICAgc3JjLFxuICAgIHJlc2FtcGxlcixcbiAgICBlcXVhbGl6ZXJTdHJlYW0sXG4gICAgcmV2ZXJiLFxuICAgIGRzcFN0cmVhbSxcbiAgICBiaXF1YWRTdHJlYW0sXG4gICAgY29tcHJlc3NvcixcbiAgICB2b2x1bWVUcmFuc2Zvcm1lcixcbiAgICBzZWVrZXJdLlxuICAgIGZpbHRlcihCb29sZWFuKSBhcyBSZWFkb25seTxSZWFkYWJsZVtdPjtcblxuICAgIGlmICghY2hhaW5zLmxlbmd0aCkgcmV0dXJuIHNyYztcblxuICAgIC8vIEB0cy1pZ25vcmVcbiAgICB0aGlzLmRlc3RpbmF0aW9uID0gcGlwZWxpbmUoLi4uY2hhaW5zLCAoZXJyOiBFcnJvciB8IG51bGwpID0+IHtcbiAgICAgIGlmIChlcnIpIHtcbiAgICAgICAgdGhpcy5kZXN0cm95KCk7XG4gICAgICAgIGlmICghZXJyLm1lc3NhZ2UuaW5jbHVkZXMoJ0VSUl9TVFJFQU1fUFJFTUFUVVJFX0NMT1NFJykpXG4gICAgICAgIHRoaXMub25FcnJvcihlcnIpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgdGhpcy5kZXN0aW5hdGlvbiEub25jZSgnY2xvc2UnLCB0aGlzLmRlc3Ryb3kuYmluZCh0aGlzKSk7XG5cbiAgICByZXR1cm4gdGhpcy5kZXN0aW5hdGlvbiBhcyBSZWFkYWJsZTtcbiAgfVxuXG4gIHB1YmxpYyBkZXN0cm95KCkge1xuICAgIC8vIGNsZWFudXBcbiAgICB0aGlzLnJlc2FtcGxlcj8uZGVzdHJveSgpO1xuICAgIHRoaXMuZXF1YWxpemVyPy5kZXN0cm95KCk7XG4gICAgdGhpcy5iaXF1YWQ/LmRlc3Ryb3koKTtcbiAgICB0aGlzLmZpbHRlcnM/LmRlc3Ryb3koKTtcbiAgICB0aGlzLnZvbHVtZT8uZGVzdHJveSgpO1xuICAgIHRoaXMuY29tcHJlc3Nvcj8uZGVzdHJveSgpO1xuICAgIHRoaXMuc2Vla2VyPy5kZXN0cm95KCk7XG4gICAgdGhpcy5yZXZlcmI/LmRlc3Ryb3koKTtcbiAgICB0aGlzLmRlc3RpbmF0aW9uPy5kZXN0cm95KCk7XG4gICAgdGhpcy5zb3VyY2U/LmRlc3Ryb3koKTtcblxuICAgIC8vIHJlbW92ZSBldmVudHNcbiAgICB0aGlzLnJlc2FtcGxlcj8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgdGhpcy5lcXVhbGl6ZXI/LnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIHRoaXMuYmlxdWFkPy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLmZpbHRlcnM/LnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIHRoaXMudm9sdW1lPy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLmNvbXByZXNzb3I/LnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIHRoaXMuc2Vla2VyPy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLnJldmVyYj8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgdGhpcy5kZXN0aW5hdGlvbj8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgdGhpcy5zb3VyY2U/LnJlbW92ZUFsbExpc3RlbmVycygpO1xuXG4gICAgLy8gdW5yZWZcbiAgICB0aGlzLnJlc2FtcGxlciA9IG51bGw7XG4gICAgdGhpcy5lcXVhbGl6ZXIgPSBudWxsO1xuICAgIHRoaXMuYmlxdWFkID0gbnVsbDtcbiAgICB0aGlzLmZpbHRlcnMgPSBudWxsO1xuICAgIHRoaXMudm9sdW1lID0gbnVsbDtcbiAgICB0aGlzLmNvbXByZXNzb3IgPSBudWxsO1xuICAgIHRoaXMuc2Vla2VyID0gbnVsbDtcbiAgICB0aGlzLnJldmVyYiA9IG51bGw7XG4gICAgdGhpcy5kZXN0aW5hdGlvbiA9IG51bGw7XG4gICAgdGhpcy5zb3VyY2UgPSBudWxsO1xuICB9XG59IiwgIlxuXG5cblxuXG5cbmV4cG9ydCBjb25zdCB2ZXJzaW9uID0gLyogQF9fTUFDUk9fXyBnZXRWZXJzaW9uICovXCI3LjIuMFwiOyJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUNBTyxJQUFNLGFBQWE7QUFBQSxFQUN4Qix5QkFBeUI7QUFBQSxFQUN6QixtQkFBbUI7QUFBQSxFQUNuQixTQUFTO0FBQUEsRUFDVCxVQUFVO0FBQUEsRUFDVixVQUFVO0FBQUEsRUFDVixPQUFPO0FBQUEsRUFDUCxTQUFTO0FBQUEsRUFDVCxVQUFVO0FBQUEsRUFDVixXQUFXO0FBQUEsRUFDWCxXQUFXO0FBQ2I7QUFjTyxJQUFNLGdC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SSxPQUFRLFFBQU8sV0FBVyxLQUFLO0FBQ25DLFFBQUksT0FBUSxRQUFPLFdBQVcsS0FBSztBQUVuQyxVQUFNLFNBQVM7QUFBQSxNQUNmO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxJQUFNLEVBQ04sT0FBTyxPQUFPO0FBRWQsUUFBSSxDQUFDLE9BQU8sT0FBUSxRQUFPO0FBRzNCLFNBQUssa0JBQWMseUJBQVMsR0FBRyxRQUFRLENBQUMsUUFBc0I7QUFDNUQsVUFBSSxLQUFLO0FBQ1AsYUFBSyxRQUFRO0FBQ2IsWUFBSSxDQUFDLElBQUksUUFBUSxTQUFTLDRCQUE0QjtBQUN0RCxlQUFLLFFBQVEsR0FBRztBQUFBLE1BQ2xCO0FBQUEsSUFDRixDQUFDO0FBRUQsU0FBSyxZQUFhLEtBQUssU0FBUyxLQUFLLFFBQVEsS0FBSyxJQUFJLENBQUM7QUFFdkQsV0FBTyxLQUFLO0FBQUEsRUFDZDtBQUFBLEVBRU8sVUFBVTtBQUVmLFNBQUssV0FBVyxRQUFRO0FBQ3hCLFNBQUssV0FBVyxRQUFRO0FBQ3hCLFNBQUssUUFBUSxRQUFRO0FBQ3JCLFNBQUssU0FBUyxRQUFRO0FBQ3RCLFNBQUssUUFBUSxRQUFRO0FBQ3JCLFNBQUssWUFBWSxRQUFRO0FBQ3pCLFNBQUssUUFBUSxRQUFRO0FBQ3JCLFNBQUssUUFBUSxRQUFRO0FBQ3JCLFNBQUssYUFBYSxRQUFRO0FBQzFCLFNBQUssUUFBUSxRQUFRO0FBR3JCLFNBQUssV0FBVyxtQkFBbUI7QUFDbkMsU0FBSyxXQUFXLG1CQUFtQjtBQUNuQyxTQUFLLFFBQVEsbUJBQW1CO0FBQ2hDLFNBQUssU0FBUyxtQkFBbUI7QUFDakMsU0FBSyxRQUFRLG1CQUFtQjtBQUNoQyxTQUFLLFlBQVksbUJBQW1CO0FBQ3BDLFNBQUssUUFBUSxtQkFBbUI7QUFDaEMsU0FBSyxRQUFRLG1CQUFtQjtBQUNoQyxTQUFLLGFBQWEsbUJBQW1CO0FBQ3JDLFNBQUssUUFBUSxtQkFBbUI7QUFHaEMsU0FBSyxZQUFZO0FBQ2pCLFNBQUssWUFBWTtBQUNqQixTQUFLLFNBQVM7QUFDZCxTQUFLLFVBQVU7QUFDZixTQUFLLFNBQVM7QUFDZCxTQUFLLGFBQWE7QUFDbEIsU0FBSyxTQUFTO0FBQ2QsU0FBSyxTQUFTO0FBQ2QsU0FBSyxjQUFjO0FBQ25CLFNBQUssU0FBUztBQUFBLEVBQ2hCO0FBQ0Y7QUF6STBCO0FBQW5CLElBQU0sZUFBTjs7O0FDekJBLElBQU07QUFBQTtBQUFBLEVBQXFDO0FBQUE7IiwKICAibmFtZXMiOiBbImltcG9ydF9zdHJlYW0iXQp9Cg==
|