1624 lines
171 KiB
JavaScript
1624 lines
171 KiB
JavaScript
var __defProp = Object.defineProperty;
|
|
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 __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
|
|
// 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
|
|
import { Transform } from "stream";
|
|
var _PCMTransformer = class _PCMTransformer extends 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
|
|
import { EventEmitter } from "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 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
|
|
import { pipeline } from "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 = 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"
|
|
);
|
|
export {
|
|
AF_NIGHTCORE_RATE,
|
|
AF_VAPORWAVE_RATE,
|
|
AudioFilter,
|
|
AudioFilters,
|
|
BASS_EQ_BANDS,
|
|
BiquadFilter,
|
|
BiquadStream,
|
|
ChannelProcessor,
|
|
Coefficients,
|
|
CompressorTransformer,
|
|
Equalizer,
|
|
EqualizerCoefficients,
|
|
EqualizerConfiguration,
|
|
EqualizerStream,
|
|
FilterType,
|
|
FiltersChain,
|
|
Frequency,
|
|
MonoStereoTransformer,
|
|
transformers_exports as PCMAudioTransformer,
|
|
PCMResampler,
|
|
PCMSeekerTransformer,
|
|
PCMTransformer,
|
|
Q_BUTTERWORTH,
|
|
ReverbTransformer,
|
|
VolumeTransformer,
|
|
version
|
|
};
|
|
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2JpcXVhZC9Db2VmZmljaWVudHMudHMiLCAiLi4vc3JjL2JpcXVhZC9CaXF1YWQudHMiLCAiLi4vc3JjL3V0aWxzL0ZyZXF1ZW5jeS50cyIsICIuLi9zcmMvdXRpbHMvUENNVHJhbnNmb3JtZXIudHMiLCAiLi4vc3JjL2JpcXVhZC9CaXF1YWRTdHJlYW0udHMiLCAiLi4vc3JjL2VxdWFsaXplci9DaGFubmVsUHJvY2Vzc29yLnRzIiwgIi4uL3NyYy9lcXVhbGl6ZXIvQ29lZmZpY2llbnRzLnRzIiwgIi4uL3NyYy9lcXVhbGl6ZXIvRXF1YWxpemVyQ29uZmlndXJhdGlvbi50cyIsICIuLi9zcmMvZXF1YWxpemVyL0VxdWFsaXplci50cyIsICIuLi9zcmMvZXF1YWxpemVyL0VxdWFsaXplclN0cmVhbS50cyIsICIuLi9zcmMvYXVkaW8vTW9ub1N0ZXJlb1RyYW5zZm9ybWVyLnRzIiwgIi4uL3NyYy9hdWRpby90cmFuc2Zvcm1lcnMvaW5kZXgudHMiLCAiLi4vc3JjL2F1ZGlvL3RyYW5zZm9ybWVycy9iaXF1YWQudHMiLCAiLi4vc3JjL2F1ZGlvL3RyYW5zZm9ybWVycy9kc3AudHMiLCAiLi4vc3JjL2F1ZGlvL3RyYW5zZm9ybWVycy9lcXVhbGl6ZXIudHMiLCAiLi4vc3JjL2F1ZGlvL0F1ZGlvRmlsdGVyLnRzIiwgIi4uL3NyYy9hdWRpby9QQ01SZXNhbXBsZXIudHMiLCAiLi4vc3JjL2F1ZGlvL1ZvbHVtZVRyYW5zZm9ybWVyLnRzIiwgIi4uL3NyYy9hdWRpby9Db21wcmVzc29yVHJhbnNmb3JtZXIudHMiLCAiLi4vc3JjL2F1ZGlvL1BDTVNlZWtlclRyYW5zZm9ybWVyLnRzIiwgIi4uL3NyYy9hdWRpby9SZXZlcmJUcmFuc2Zvcm1lci50cyIsICIuLi9zcmMvRmlsdGVyc0NoYWluQnVpbGRlci50cyIsICIuLi9zcmMvdmVyc2lvbi50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiZXhwb3J0IGNvbnN0IEZpbHRlclR5cGUgPSB7XG4gIFNpbmdsZVBvbGVMb3dQYXNzQXBwcm94OiAwLFxuICBTaW5nbGVQb2xlTG93UGFzczogMSxcbiAgTG93UGFzczogMixcbiAgSGlnaFBhc3M6IDMsXG4gIEJhbmRQYXNzOiA0LFxuICBOb3RjaDogNSxcbiAgQWxsUGFzczogNixcbiAgTG93U2hlbGY6IDcsXG4gIEhpZ2hTaGVsZjogOCxcbiAgUGVha2luZ0VROiA5XG59IGFzIGNvbnN0O1xuXG5leHBvcnQgdHlwZSBCaXF1YWRGaWx0ZXJzID1cbmtleW9mIHR5cGVvZiBGaWx0ZXJUeXBlIHxcbih0eXBlb2YgRmlsdGVyVHlwZSlba2V5b2YgdHlwZW9mIEZpbHRlclR5cGVdO1xuXG5pbnRlcmZhY2UgQ29lZmZpY2llbnRzSW5pdCB7XG4gIGExOiBudW1iZXI7XG4gIGEyOiBudW1iZXI7XG4gIGIwOiBudW1iZXI7XG4gIGIxOiBudW1iZXI7XG4gIGIyOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjb25zdCBRX0JVVFRFUldPUlRIID0gTWF0aC5TUVJUMV8yO1xuXG5leHBvcnQgY2xhc3MgQ29lZmZpY2llbnRzIHtcbiAgLy8gRGVub21pbmF0b3IgY29lZmZpY2llbnRzXG4gIHB1YmxpYyBhMSA9IDA7XG4gIHB1YmxpYyBhMiA9IDA7XG5cbiAgLy8gTm9taW5hdG9yIGNvZWZmaWNpZW50c1xuICBwdWJsaWMgYjAgPSAwO1xuICBwdWJsaWMgYjEgPSAwO1xuICBwdWJsaWMgYjIgPSAwO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihkYXRhPzogQ29lZmZpY2llbnRzSW5pdCkge1xuICAgIGlmIChkYXRhKSB7XG4gICAgICB0aGlzLmExID0gZGF0YS5hMTtcbiAgICAgIHRoaXMuYTIgPSBkYXRhLmEyO1xuICAgICAgdGhpcy5iMCA9IGRhdGEuYjA7XG4gICAgICB0aGlzLmIxID0gZGF0YS5iMTtcbiAgICAgIHRoaXMuYjIgPSBkYXRhLmIyO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBzdGF0aWMgZnJvbShcbiAgZmlsdGVyOiBCaXF1YWRGaWx0ZXJzLFxuICBzYW1wbGluZ0ZyZXE6IG51bWJlcixcbiAgY3V0b2ZmRnJlcTogbnVtYmVyLFxuICBROiBudW1iZXIsXG4gIGRiR2FpbiA9IC0xMClcbiAge1xuICAgIGlmICgyLjAgKiBjdXRvZmZGcmVxID4gc2FtcGxpbmdGcmVxKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYEN1dG9mZiBmcmVxdWVuY3kgaXMgdG9vIGJpZyFgKTtcbiAgICB9XG5cbiAgICBpZiAoUSA8IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihgUSBtYXkgbm90IGJlIG5lZ2F0aXZlYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgb21lZ2EgPSAyLjAgKiBNYXRoLlBJICogY3V0b2ZmRnJlcSAvIHNhbXBsaW5nRnJlcTtcblxuICAgIGNvbnN0IGJxZiA9IHR5cGVvZiBmaWx0ZXIgPT09ICdzdHJpbmcnID8gRmlsdGVyVHlwZVtmaWx0ZXJdIDogZmlsdGVyO1xuXG4gICAgc3dpdGNoIChicWYpIHtcbiAgICAgIGNhc2UgRmlsdGVyVHlwZS5TaW5nbGVQb2xlTG93UGFzc0FwcHJveDp7XG4gICAgICAgICAgY29uc3QgYWxwaGEgPSBvbWVnYSAvIChvbWVnYSArIDEuMCk7XG5cbiAgICAgICAgICByZXR1cm4gbmV3IENvZWZmaWNpZW50cyh7XG4gICAgICAgICAgICBhMTogYWxwaGEgLSAxLjAsXG4gICAgICAgICAgICBhMjogMC4wLFxuICAgICAgICAgICAgYjA6IGFscGhhLFxuICAgICAgICAgICAgYjE6IDAuMCxcbiAgICAgICAgICAgIGIyOiAwLjBcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSBGaWx0ZXJUeXBlLlNpbmdsZVBvbGVMb3dQYXNzOntcbiAgICAgICAgICBjb25zdCBvbWVnYV90ID0gTWF0aC50YW4ob21lZ2EgLyAyLjApO1xuICAgICAgICAgIGNvbnN0IGEwID0gMS4wICsgb21lZ2FfdDtcblxuICAgICAgICAgIHJldHVybiBuZXcgQ29lZmZpY2llbnRzKHtcbiAgICAgICAgICAgIGExOiAob21lZ2FfdCAtIDEuMCkgLyBhMCxcbiAgICAgICAgICAgIGEyOiAwLjAsXG4gICAgICAgICAgICBiMDogb21lZ2FfdCAvIGEwLFxuICAgICAgICAgICAgYjE6IG9tZWdhX3QgLyBhMCxcbiAgICAgICAgICAgIGIyOiAwLjBcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSBGaWx0ZXJUeXBlLkxvd1Bhc3M6e1xuICAgICAgICAgIGNvbnN0IG9tZWdhX3MgPSBNYXRoLnNpbihvbWVnYSk7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfYyA9IE1hdGguY29zKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBhbHBoYSA9IG9tZWdhX3MgLyAoMi4wICogUSk7XG5cbiAgICAgICAgICBjb25zdCBiMCA9ICgxLjAgLSBvbWVnYV9jKSAqIDAuNTtcbiAgICAgICAgICBjb25zdCBiMSA9IDEuMCAtIG9tZWdhX2M7XG4gICAgICAgICAgY29uc3QgYjIgPSAoMS4wIC0gb21lZ2FfYykgKiAwLjU7XG4gICAgICAgICAgY29uc3QgYTAgPSAxLjAgKyBhbHBoYTtcbiAgICAgICAgICBjb25zdCBhMSA9IC0yLjAgKiBvbWVnYV9jO1xuICAgICAgICAgIGNvbnN0IGEyID0gMS4wIC0gYWxwaGE7XG5cbiAgICAgICAgICBjb25zdCBkaXYgPSAxLjAgLyBhMDtcblxuICAgICAgICAgIHJldHVybiBuZXcgQ29lZmZpY2llbnRzKHtcbiAgICAgICAgICAgIGExOiBhMSAqIGRpdixcbiAgICAgICAgICAgIGEyOiBhMiAqIGRpdixcbiAgICAgICAgICAgIGIwOiBiMCAqIGRpdixcbiAgICAgICAgICAgIGIxOiBiMSAqIGRpdixcbiAgICAgICAgICAgIGIyOiBiMiAqIGRpdlxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICBjYXNlIEZpbHRlclR5cGUuSGlnaFBhc3M6e1xuICAgICAgICAgIGNvbnN0IG9tZWdhX3MgPSBNYXRoLnNpbihvbWVnYSk7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfYyA9IE1hdGguY29zKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBhbHBoYSA9IG9tZWdhX3MgLyAoMi4wICogUSk7XG5cbiAgICAgICAgICBjb25zdCBiMCA9ICgxLjAgKyBvbWVnYV9jKSAqIDAuNTtcbiAgICAgICAgICBjb25zdCBiMSA9IC0oMS4wICsgb21lZ2FfYyk7XG4gICAgICAgICAgY29uc3QgYjIgPSAoMS4wICsgb21lZ2FfYykgKiAwLjU7XG4gICAgICAgICAgY29uc3QgYTAgPSAxLjAgKyBhbHBoYTtcbiAgICAgICAgICBjb25zdCBhMSA9IC0yLjAgKiBvbWVnYV9jO1xuICAgICAgICAgIGNvbnN0IGEyID0gMS4wIC0gYWxwaGE7XG5cbiAgICAgICAgICBjb25zdCBkaXYgPSAxLjAgLyBhMDtcblxuICAgICAgICAgIHJldHVybiBuZXcgQ29lZmZpY2llbnRzKHtcbiAgICAgICAgICAgIGExOiBhMSAqIGRpdixcbiAgICAgICAgICAgIGEyOiBhMiAqIGRpdixcbiAgICAgICAgICAgIGIwOiBiMCAqIGRpdixcbiAgICAgICAgICAgIGIxOiBiMSAqIGRpdixcbiAgICAgICAgICAgIGIyOiBiMiAqIGRpdlxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICBjYXNlIEZpbHRlclR5cGUuTm90Y2g6e1xuICAgICAgICAgIGNvbnN0IG9tZWdhX3MgPSBNYXRoLnNpbihvbWVnYSk7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfYyA9IE1hdGguY29zKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBhbHBoYSA9IG9tZWdhX3MgLyAoMi4wICogUSk7XG5cbiAgICAgICAgICBjb25zdCBiMCA9IDEuMDtcbiAgICAgICAgICBjb25zdCBiMSA9IC0yLjAgKiBvbWVnYV9jO1xuICAgICAgICAgIGNvbnN0IGIyID0gMS4wO1xuICAgICAgICAgIGNvbnN0IGEwID0gMS4wICsgYWxwaGE7XG4gICAgICAgICAgY29uc3QgYTEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBhMiA9IDEuMCAtIGFscGhhO1xuXG4gICAgICAgICAgY29uc3QgZGl2ID0gMS4wIC8gYTA7XG5cbiAgICAgICAgICByZXR1cm4gbmV3IENvZWZmaWNpZW50cyh7XG4gICAgICAgICAgICBhMTogYTEgKiBkaXYsXG4gICAgICAgICAgICBhMjogYTIgKiBkaXYsXG4gICAgICAgICAgICBiMDogYjAgKiBkaXYsXG4gICAgICAgICAgICBiMTogYjEgKiBkaXYsXG4gICAgICAgICAgICBiMjogYjIgKiBkaXZcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgY2FzZSBGaWx0ZXJUeXBlLkJhbmRQYXNzOntcbiAgICAgICAgICBjb25zdCBvbWVnYV9zID0gTWF0aC5zaW4ob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IG9tZWdhX2MgPSBNYXRoLmNvcyhvbWVnYSk7XG4gICAgICAgICAgY29uc3QgYWxwaGEgPSBvbWVnYV9zIC8gKDIuMCAqIFEpO1xuXG4gICAgICAgICAgY29uc3QgYjAgPSBvbWVnYV9zIC8gMi4wO1xuICAgICAgICAgIGNvbnN0IGIxID0gMDtcbiAgICAgICAgICBjb25zdCBiMiA9IC0ob21lZ2FfcyAvIDIuMCk7XG4gICAgICAgICAgY29uc3QgYTAgPSAxLjAgKyBhbHBoYTtcbiAgICAgICAgICBjb25zdCBhMSA9IC0yLjAgKiBvbWVnYV9jO1xuICAgICAgICAgIGNvbnN0IGEyID0gMS4wIC0gYWxwaGE7XG5cbiAgICAgICAgICBjb25zdCBkaXYgPSAxLjAgLyBhMDtcblxuICAgICAgICAgIHJldHVybiBuZXcgQ29lZmZpY2llbnRzKHtcbiAgICAgICAgICAgIGExOiBhMSAqIGRpdixcbiAgICAgICAgICAgIGEyOiBhMiAqIGRpdixcbiAgICAgICAgICAgIGIwOiBiMCAqIGRpdixcbiAgICAgICAgICAgIGIxOiBiMSAqIGRpdixcbiAgICAgICAgICAgIGIyOiBiMiAqIGRpdlxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICBjYXNlIEZpbHRlclR5cGUuQWxsUGFzczp7XG4gICAgICAgICAgY29uc3Qgb21lZ2FfcyA9IE1hdGguc2luKG9tZWdhKTtcbiAgICAgICAgICBjb25zdCBvbWVnYV9jID0gTWF0aC5jb3Mob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IGFscGhhID0gb21lZ2FfcyAvICgyLjAgKiBRKTtcblxuICAgICAgICAgIGNvbnN0IGIwID0gMS4wIC0gYWxwaGE7XG4gICAgICAgICAgY29uc3QgYjEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBiMiA9IDEuMCArIGFscGhhO1xuICAgICAgICAgIGNvbnN0IGEwID0gMS4wICsgYWxwaGE7XG4gICAgICAgICAgY29uc3QgYTEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBhMiA9IDEuMCAtIGFscGhhO1xuXG4gICAgICAgICAgcmV0dXJuIG5ldyBDb2VmZmljaWVudHMoe1xuICAgICAgICAgICAgYTE6IGExIC8gYTAsXG4gICAgICAgICAgICBhMjogYTIgLyBhMCxcbiAgICAgICAgICAgIGIwOiBiMCAvIGEwLFxuICAgICAgICAgICAgYjE6IGIxIC8gYTAsXG4gICAgICAgICAgICBiMjogYjIgLyBhMFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICBjYXNlIEZpbHRlclR5cGUuTG93U2hlbGY6e1xuICAgICAgICAgIGNvbnN0IGEgPSBNYXRoLnBvdygxMC4wLCBkYkdhaW4gLyA0MC4wKTtcbiAgICAgICAgICBjb25zdCBvbWVnYV9zID0gTWF0aC5zaW4ob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IG9tZWdhX2MgPSBNYXRoLmNvcyhvbWVnYSk7XG4gICAgICAgICAgY29uc3QgYWxwaGEgPSBvbWVnYV9zIC8gKDIuMCAqIFEpO1xuXG4gICAgICAgICAgY29uc3QgYjAgPVxuICAgICAgICAgIGEgKiAoYSArIDEuMCAtIChhIC0gMS4wKSAqIG9tZWdhX2MgKyAyLjAgKiBhbHBoYSAqIE1hdGguc3FydChhKSk7XG4gICAgICAgICAgY29uc3QgYjEgPSAyLjAgKiBhICogKGEgLSAxLjAgLSAoYSArIDEuMCkgKiBvbWVnYV9jKTtcbiAgICAgICAgICBjb25zdCBiMiA9XG4gICAgICAgICAgYSAqIChhICsgMS4wIC0gKGEgLSAxLjApICogb21lZ2FfYyAtIDIuMCAqIGFscGhhICogTWF0aC5zcXJ0KGEpKTtcbiAgICAgICAgICBjb25zdCBhMCA9IGEgKyAxLjAgKyAoYSAtIDEuMCkgKiBvbWVnYV9jICsgMi4wICogYWxwaGEgKiBNYXRoLnNxcnQoYSk7XG4gICAgICAgICAgY29uc3QgYTEgPSAtMi4wICogKGEgLSAxLjAgKyAoYSArIDEuMCkgKiBvbWVnYV9jKTtcbiAgICAgICAgICBjb25zdCBhMiA9IGEgKyAxLjAgKyAoYSAtIDEuMCkgKiBvbWVnYV9jIC0gMi4wICogYWxwaGEgKiBNYXRoLnNxcnQoYSk7XG5cbiAgICAgICAgICByZXR1cm4gbmV3IENvZWZmaWNpZW50cyh7XG4gICAgICAgICAgICBhMTogYTEgLyBhMCxcbiAgICAgICAgICAgIGEyOiBhMiAvIGEwLFxuICAgICAgICAgICAgYjA6IGIwIC8gYTAsXG4gICAgICAgICAgICBiMTogYjEgLyBhMCxcbiAgICAgICAgICAgIGIyOiBiMiAvIGEwXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgRmlsdGVyVHlwZS5IaWdoU2hlbGY6e1xuICAgICAgICAgIGNvbnN0IGEgPSBNYXRoLnBvdygxMC4wLCBkYkdhaW4gLyA0MC4wKTtcbiAgICAgICAgICBjb25zdCBvbWVnYV9zID0gTWF0aC5zaW4ob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IG9tZWdhX2MgPSBNYXRoLmNvcyhvbWVnYSk7XG4gICAgICAgICAgY29uc3QgYWxwaGEgPSBvbWVnYV9zIC8gKDIuMCAqIFEpO1xuXG4gICAgICAgICAgY29uc3QgYjAgPVxuICAgICAgICAgIGEgKiAoYSArIDEuMCArIChhIC0gMS4wKSAqIG9tZWdhX2MgKyAyLjAgKiBhbHBoYSAqIE1hdGguc3FydChhKSk7XG4gICAgICAgICAgY29uc3QgYjEgPSAtMi4wICogYSAqIChhIC0gMS4wICsgKGEgKyAxLjApICogb21lZ2FfYyk7XG4gICAgICAgICAgY29uc3QgYjIgPVxuICAgICAgICAgIGEgKiAoYSArIDEuMCArIChhIC0gMS4wKSAqIG9tZWdhX2MgLSAyLjAgKiBhbHBoYSAqIE1hdGguc3FydChhKSk7XG4gICAgICAgICAgY29uc3QgYTAgPSBhICsgMS4wIC0gKGEgLSAxLjApICogb21lZ2FfYyArIDIuMCAqIGFscGhhICogTWF0aC5zcXJ0KGEpO1xuICAgICAgICAgIGNvbnN0IGExID0gMi4wICogKGEgLSAxLjAgLSAoYSArIDEuMCkgKiBvbWVnYV9jKTtcbiAgICAgICAgICBjb25zdCBhMiA9IGEgKyAxLjAgLSAoYSAtIDEuMCkgKiBvbWVnYV9jIC0gMi4wICogYWxwaGEgKiBNYXRoLnNxcnQoYSk7XG5cbiAgICAgICAgICByZXR1cm4gbmV3IENvZWZmaWNpZW50cyh7XG4gICAgICAgICAgICBhMTogYTEgLyBhMCxcbiAgICAgICAgICAgIGEyOiBhMiAvIGEwLFxuICAgICAgICAgICAgYjA6IGIwIC8gYTAsXG4gICAgICAgICAgICBiMTogYjEgLyBhMCxcbiAgICAgICAgICAgIGIyOiBiMiAvIGEwXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIGNhc2UgRmlsdGVyVHlwZS5QZWFraW5nRVE6e1xuICAgICAgICAgIGNvbnN0IGEgPSBNYXRoLnBvdygxMC4wLCBkYkdhaW4gLyA0MC4wKTtcbiAgICAgICAgICBjb25zdCBvbWVnYV9zID0gTWF0aC5zaW4ob21lZ2EpO1xuICAgICAgICAgIGNvbnN0IG9tZWdhX2MgPSBNYXRoLmNvcyhvbWVnYSk7XG4gICAgICAgICAgY29uc3QgYWxwaGEgPSBvbWVnYV9zIC8gKDIuMCAqIFEpO1xuXG4gICAgICAgICAgY29uc3QgYjAgPSAxLjAgKyBhbHBoYSAqIGE7XG4gICAgICAgICAgY29uc3QgYjEgPSAtMi4wICogb21lZ2FfYztcbiAgICAgICAgICBjb25zdCBiMiA9IDEuMCAtIGFscGhhICogYTtcbiAgICAgICAgICBjb25zdCBhMCA9IDEuMCArIGFscGhhIC8gYTtcbiAgICAgICAgICBjb25zdCBhMSA9IC0yLjAgKiBvbWVnYV9jO1xuICAgICAgICAgIGNvbnN0IGEyID0gMS4wIC0gYWxwaGEgLyBhO1xuXG4gICAgICAgICAgcmV0dXJuIG5ldyBDb2VmZmljaWVudHMoe1xuICAgICAgICAgICAgYTE6IGExIC8gYTAsXG4gICAgICAgICAgICBhMjogYTIgLyBhMCxcbiAgICAgICAgICAgIGIwOiBiMCAvIGEwLFxuICAgICAgICAgICAgYjE6IGIxIC8gYTAsXG4gICAgICAgICAgICBiMjogYjIgLyBhMFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIGZpbHRlciB0eXBlIFwiJHtmaWx0ZXJ9XCJgKTtcbiAgICB9XG4gIH1cbn0iLCAiaW1wb3J0IHsgQmlxdWFkRmlsdGVycywgQ29lZmZpY2llbnRzIH0gZnJvbSAnLi9Db2VmZmljaWVudHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIEJpcXVhZFNldEZpbHRlclByb3BzIHtcbiAgZjA6IG51bWJlcjtcbiAgZnM6IG51bWJlcjtcbiAgUTogbnVtYmVyO1xuICBnYWluPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgQmlxdWFkRmlsdGVyIHtcbiAgcHVibGljIHgxID0gMC4wO1xuICBwdWJsaWMgeDIgPSAwLjA7XG4gIHB1YmxpYyB5MSA9IDAuMDtcbiAgcHVibGljIHkyID0gMC4wO1xuICBwdWJsaWMgczEgPSAwLjA7XG4gIHB1YmxpYyBzMiA9IDAuMDtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIGNvZWZmaWNpZW50czogQ29lZmZpY2llbnRzKSB7fVxuXG4gIHB1YmxpYyBzZXRGaWx0ZXIoZmlsdGVyOiBCaXF1YWRGaWx0ZXJzLCBvcHRpb25zOiBCaXF1YWRTZXRGaWx0ZXJQcm9wcykge1xuICAgIGNvbnN0IGNvZWZmaWNpZW50cyA9IENvZWZmaWNpZW50cy5mcm9tKFxuICAgICAgZmlsdGVyLFxuICAgICAgb3B0aW9ucy5mcyxcbiAgICAgIG9wdGlvbnMuZjAsXG4gICAgICBvcHRpb25zLlEsXG4gICAgICBvcHRpb25zLmdhaW5cbiAgICApO1xuXG4gICAgdGhpcy51cGRhdGUoY29lZmZpY2llbnRzKTtcbiAgfVxuXG4gIHB1YmxpYyB1cGRhdGUoY29lZmZpY2llbnRzOiBDb2VmZmljaWVudHMpIHtcbiAgICB0aGlzLmNvZWZmaWNpZW50cyA9IGNvZWZmaWNpZW50cztcbiAgfVxuXG4gIHB1YmxpYyByZXBsYWNlKGNvZWZmaWNpZW50czogQ29lZmZpY2llbnRzKSB7XG4gICAgdGhpcy5jb2VmZmljaWVudHMgPSBjb2VmZmljaWVudHM7XG4gIH1cblxuICBwdWJsaWMgcmVzZXQoKSB7XG4gICAgdGhpcy54MSA9IDAuMDtcbiAgICB0aGlzLngyID0gMC4wO1xuICAgIHRoaXMueTEgPSAwLjA7XG4gICAgdGhpcy55MiA9IDAuMDtcbiAgICB0aGlzLnMxID0gMC4wO1xuICAgIHRoaXMuczIgPSAwLjA7XG4gIH1cblxuICBwdWJsaWMgcnVuKGlucHV0OiBudW1iZXIpIHtcbiAgICBjb25zdCB7IGExLCBhMiwgYjAsIGIxLCBiMiB9ID0gdGhpcy5jb2VmZmljaWVudHM7XG5cbiAgICBjb25zdCBvdXQgPVxuICAgIGIwICogaW5wdXQgKyBiMSAqIHRoaXMueDEgKyBiMiAqIHRoaXMueDIgLSBhMSAqIHRoaXMueTEgLSBhMiAqIHRoaXMueTI7XG5cbiAgICB0aGlzLngyID0gdGhpcy54MTtcbiAgICB0aGlzLngxID0gaW5wdXQ7XG4gICAgdGhpcy55MiA9IHRoaXMueTE7XG4gICAgdGhpcy55MSA9IG91dDtcblxuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICBwdWJsaWMgcnVuVHJhbnNwb3NlZChpbnB1dDogbnVtYmVyKSB7XG4gICAgY29uc3QgeyBhMSwgYTIsIGIwLCBiMSwgYjIgfSA9IHRoaXMuY29lZmZpY2llbnRzO1xuXG4gICAgY29uc3Qgb3V0ID0gdGhpcy5zMSArIGIwICogaW5wdXQ7XG5cbiAgICB0aGlzLnMxID0gdGhpcy5zMiArIGIxICogaW5wdXQgLSBhMSAqIG91dDtcbiAgICB0aGlzLnMyID0gYjIgKiBpbnB1dCAtIGEyICogb3V0O1xuXG4gICAgcmV0dXJuIG91dDtcbiAgfVxufSIsICJleHBvcnQgY2xhc3MgRnJlcXVlbmN5IHtcbiAgcHVibGljIGNvbnN0cnVjdG9yKHByaXZhdGUgX192YWw6IG51bWJlcikge1xuICAgIGlmICh0eXBlb2YgX192YWwgIT09ICdudW1iZXInIHx8IGlzTmFOKF9fdmFsKSB8fCBfX3ZhbCA9PT0gSW5maW5pdHkpXG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignRnJlcXVlbmN5IHZhbHVlIG11c3QgYmUgYSBudW1iZXInKTtcbiAgICBpZiAodGhpcy5fX3ZhbCA8IDApXG4gICAgdGhyb3cgbmV3IEVycm9yKGBGcmVxdWVuY3kgdmFsdWUgY2Fubm90IGJlIG5lZ2F0aXZlICgke19fdmFsfSlgKTtcbiAgfVxuXG4gIHB1YmxpYyBraHooKSB7XG4gICAgcmV0dXJuIHRoaXMuX192YWwgKiAxMDAwLjA7XG4gIH1cblxuICBwdWJsaWMgbWh6KCkge1xuICAgIHJldHVybiB0aGlzLl9fdmFsICogMV8wMDBfMDAwLjA7XG4gIH1cblxuICBwdWJsaWMgaHooKSB7XG4gICAgcmV0dXJuIHRoaXMuX192YWw7XG4gIH1cblxuICBwdWJsaWMgZHQoKSB7XG4gICAgcmV0dXJuIDEuMCAvIHRoaXMuX192YWw7XG4gIH1cblxuICBwdWJsaWMgdmFsdWVPZigpIHtcbiAgICByZXR1cm4gdGhpcy5fX3ZhbDtcbiAgfVxuXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gYCR7dGhpcy5fX3ZhbH1IemA7XG4gIH1cblxuICBwdWJsaWMgdG9KU09OKCkge1xuICAgIHJldHVybiB0aGlzLnRvU3RyaW5nKCk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgVHJhbnNmb3JtLCBUcmFuc2Zvcm1PcHRpb25zIH0gZnJvbSAnc3RyZWFtJztcblxuZXhwb3J0IHR5cGUgUENNVHlwZSA9IGBzJHsxNiB8IDMyfSR7J2wnIHwgJ2InfWVgO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyBleHRlbmRzIFRyYW5zZm9ybU9wdGlvbnMge1xuICB0eXBlPzogUENNVHlwZTtcbiAgZGlzYWJsZWQ/OiBib29sZWFuO1xuICBzYW1wbGVSYXRlPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgUENNVHJhbnNmb3JtZXIgZXh0ZW5kcyBUcmFuc2Zvcm0ge1xuICBwdWJsaWMgcmVhZG9ubHkgdHlwZTogUENNVHlwZSA9ICdzMTZsZSc7XG4gIHB1YmxpYyBiaXRzOiBudW1iZXI7XG4gIHB1YmxpYyBieXRlczogbnVtYmVyO1xuICBwdWJsaWMgZXh0cmVtdW06IG51bWJlcjtcbiAgcHVibGljIGRpc2FibGVkID0gZmFsc2U7XG4gIHB1YmxpYyBzYW1wbGVSYXRlID0gNDgwMDA7XG4gIHB1YmxpYyBvblVwZGF0ZSA9ICgpOiB2b2lkID0+IHtcblxuICAgIC8qIG5vb3AgKi99O1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihvcHRpb25zOiBQQ01UcmFuc2Zvcm1lck9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgb3B0aW9ucy50eXBlID8/PSAnczE2bGUnO1xuICAgIHRoaXMuZGlzYWJsZWQgPSAhIW9wdGlvbnMuZGlzYWJsZWQ7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLnNhbXBsZVJhdGUgPT09ICdudW1iZXInICYmIG9wdGlvbnMuc2FtcGxlUmF0ZSA+IDApIHtcbiAgICAgIHRoaXMuc2FtcGxlUmF0ZSA9IG9wdGlvbnMuc2FtcGxlUmF0ZTtcbiAgICB9XG5cbiAgICBzd2l0Y2ggKG9wdGlvbnMudHlwZSkge1xuICAgICAgY2FzZSAnczE2YmUnOlxuICAgICAgY2FzZSAnczE2bGUnOlxuICAgICAgICB0aGlzLnR5cGUgPSBvcHRpb25zLnR5cGU7XG4gICAgICAgIHRoaXMuYml0cyA9IDE2O1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3MzMmJlJzpcbiAgICAgIGNhc2UgJ3MzMmxlJzpcbiAgICAgICAgdGhpcy50eXBlID0gb3B0aW9ucy50eXBlO1xuICAgICAgICB0aGlzLmJpdHMgPSAzMjtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFxuICAgICAgICAgIGBFeHBlY3RlZCB0eXBlIHRvIGJlIG9uZSBvZiAkeyhcbiAgICAgICAgICBbJ3MxNmJlJywgJ3MxNmxlJywgJ3MzMmJlJywgJ3MzMmxlJ10gYXMgUENNVHlwZVtdKS5cbiAgICAgICAgICBqb2luKCcsICcpfSwgZ290IFwiJHtvcHRpb25zLnR5cGV9XCJgXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgdGhpcy5ieXRlcyA9IHRoaXMuYml0cyAvIDg7XG4gICAgdGhpcy5leHRyZW11bSA9IE1hdGgucG93KDIsIHRoaXMuYml0cyAtIDEpO1xuICB9XG5cbiAgcHVibGljIGRpc2FibGUoKSB7XG4gICAgdGhpcy5kaXNhYmxlZCA9IHRydWU7XG4gIH1cblxuICBwdWJsaWMgZW5hYmxlKCkge1xuICAgIHRoaXMuZGlzYWJsZWQgPSBmYWxzZTtcbiAgfVxuXG4gIHB1YmxpYyB0b2dnbGUoKSB7XG4gICAgdGhpcy5kaXNhYmxlZCA9ICF0aGlzLmRpc2FibGVkO1xuXG4gICAgcmV0dXJuIHRoaXMuZGlzYWJsZWQ7XG4gIH1cblxuICBwdWJsaWMgX3JlYWRJbnQoYnVmZmVyOiBCdWZmZXIsIGluZGV4OiBudW1iZXIpIHtcbiAgICBjb25zdCBtZXRob2QgPSBgcmVhZEludCR7dGhpcy50eXBlLlxuICAgIHN1YnN0cmluZygxKS5cbiAgICB0b1VwcGVyQ2FzZSgpfWAgYXMgYHJlYWRJbnQkezE2IHwgMzJ9JHsnTCcgfCAnQid9RWA7XG4gICAgcmV0dXJuIGJ1ZmZlclttZXRob2RdKGluZGV4KTtcbiAgfVxuXG4gIHB1YmxpYyBfd3JpdGVJbnQoYnVmZmVyOiBCdWZmZXIsIGludDogbnVtYmVyLCBpbmRleDogbnVtYmVyKSB7XG4gICAgY29uc3QgbWV0aG9kID0gYHdyaXRlSW50JHt0aGlzLnR5cGUuXG4gICAgc3Vic3RyaW5nKDEpLlxuICAgIHRvVXBwZXJDYXNlKCl9YCBhcyBgd3JpdGVJbnQkezE2IHwgMzJ9JHsnTCcgfCAnQid9RWA7XG4gICAgcmV0dXJuIGJ1ZmZlclttZXRob2RdKGludCwgaW5kZXgpO1xuICB9XG5cbiAgcHVibGljIGNsYW1wKHZhbDogbnVtYmVyLCBtYXggPSB0aGlzLmV4dHJlbXVtIC0gMSwgbWluID0gLXRoaXMuZXh0cmVtdW0pIHtcbiAgICByZXR1cm4gTWF0aC5taW4obWF4LCBNYXRoLm1heChtaW4sIHZhbCkpO1xuICB9XG5cbiAgcHVibGljIHNldFNhbXBsZVJhdGUocmF0ZTogbnVtYmVyKSB7XG4gICAgdGhpcy5zYW1wbGVSYXRlID0gcmF0ZTtcbiAgICByZXR1cm47XG4gIH1cbn0iLCAiaW1wb3J0IHsgVHJhbnNmb3JtQ2FsbGJhY2sgfSBmcm9tICdzdHJlYW0nO1xuaW1wb3J0IHsgUENNVHJhbnNmb3JtZXIsIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzJztcbmltcG9ydCB7IEJpcXVhZEZpbHRlciB9IGZyb20gJy4vQmlxdWFkJztcbmltcG9ydCB7XG4gIEJpcXVhZEZpbHRlcnMsXG4gIENvZWZmaWNpZW50cyxcbiAgRmlsdGVyVHlwZSxcbiAgUV9CVVRURVJXT1JUSCB9IGZyb21cbicuL0NvZWZmaWNpZW50cyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQmlxdWFkU3RyZWFtT3B0aW9ucyBleHRlbmRzIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB7XG4gIGZpbHRlcj86IEJpcXVhZEZpbHRlcnM7XG4gIFE/OiBudW1iZXI7XG4gIGN1dG9mZj86IG51bWJlcjtcbiAgZ2Fpbj86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBCaXF1YWRGaWx0ZXJVcGRhdGVEYXRhIHtcbiAgZmlsdGVyPzogQmlxdWFkRmlsdGVycztcbiAgUT86IG51bWJlcjtcbiAgY3V0b2ZmPzogbnVtYmVyO1xuICBnYWluPzogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgQmlxdWFkU3RyZWFtIGV4dGVuZHMgUENNVHJhbnNmb3JtZXIge1xuICBwdWJsaWMgYmlxdWFkITogQmlxdWFkRmlsdGVyO1xuICBwdWJsaWMgY3V0b2ZmID0gODA7XG4gIHB1YmxpYyBnYWluID0gMDtcbiAgcHVibGljIGJpcXVhZEZpbHRlciE6IEJpcXVhZEZpbHRlcnM7XG4gIHB1YmxpYyBRID0gUV9CVVRURVJXT1JUSDtcbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM6IEJpcXVhZFN0cmVhbU9wdGlvbnMgPSB7fSkge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgaWYgKCdjdXRvZmYnIGluIG9wdGlvbnMpIHRoaXMuY3V0b2ZmID0gb3B0aW9ucy5jdXRvZmYhO1xuICAgIGlmICgnZ2FpbicgaW4gb3B0aW9ucykgdGhpcy5nYWluID0gb3B0aW9ucy5nYWluITtcbiAgICBpZiAoJ1EnIGluIG9wdGlvbnMpIHRoaXMuUSA9IG9wdGlvbnMuUSE7XG4gICAgaWYgKCdiaXF1YWRGaWx0ZXInIGluIG9wdGlvbnMpIHtcbiAgICAgIGlmIChcbiAgICAgIHR5cGVvZiBvcHRpb25zLmJpcXVhZEZpbHRlciA9PT0gJ3N0cmluZycgfHxcbiAgICAgIHR5cGVvZiBvcHRpb25zLmJpcXVhZEZpbHRlciA9PT0gJ251bWJlcicpXG5cbiAgICAgIHRoaXMuYmlxdWFkRmlsdGVyID0gb3B0aW9ucy5maWx0ZXIhO1xuICAgICAgaWYgKHRoaXMuYmlxdWFkRmlsdGVyICE9IG51bGwpIHtcbiAgICAgICAgdGhpcy5iaXF1YWQgPSBuZXcgQmlxdWFkRmlsdGVyKFxuICAgICAgICAgIENvZWZmaWNpZW50cy5mcm9tKFxuICAgICAgICAgICAgdGhpcy5iaXF1YWRGaWx0ZXIsXG4gICAgICAgICAgICB0aGlzLnNhbXBsZVJhdGUsXG4gICAgICAgICAgICB0aGlzLmN1dG9mZixcbiAgICAgICAgICAgIHRoaXMuUSxcbiAgICAgICAgICAgIHRoaXMuZ2FpblxuICAgICAgICAgIClcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwdWJsaWMgZ2V0IGZpbHRlcnMoKSB7XG4gICAgcmV0dXJuIHRoaXMuYmlxdWFkRmlsdGVyO1xuICB9XG5cbiAgcHVibGljIHNldCBmaWx0ZXJzKGY6IEJpcXVhZEZpbHRlcnMpIHtcbiAgICBpZiAoZiA9PSBudWxsIHx8IHR5cGVvZiBmID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgZiA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMudXBkYXRlKHsgZmlsdGVyOiBmIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKGBJbnZhbGlkIGJpcXVhZCBmaWx0ZXIgdHlwZSBcIiR7Zn1cImApO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRGaWx0ZXJOYW1lKCkge1xuICAgIGlmICh0aGlzLmJpcXVhZEZpbHRlciA9PSBudWxsKSByZXR1cm4gbnVsbDtcbiAgICBpZiAodHlwZW9mIHRoaXMuYmlxdWFkRmlsdGVyID09PSAnc3RyaW5nJykgcmV0dXJuIHRoaXMuYmlxdWFkRmlsdGVyO1xuICAgIHJldHVybiBPYmplY3QuZW50cmllcyhGaWx0ZXJUeXBlKS5maW5kKFxuICAgICAgKHIpID0+IHJbMV0gPT09IHRoaXMuYmlxdWFkRmlsdGVyXG4gICAgKT8uWzBdIGFzIEJpcXVhZEZpbHRlcnM7XG4gIH1cblxuICBwdWJsaWMgdXBkYXRlKG9wdGlvbnM6IEJpcXVhZEZpbHRlclVwZGF0ZURhdGEpIHtcbiAgICBpZiAoJ2N1dG9mZicgaW4gb3B0aW9ucykgdGhpcy5jdXRvZmYgPSBvcHRpb25zLmN1dG9mZiE7XG4gICAgaWYgKCdnYWluJyBpbiBvcHRpb25zKSB0aGlzLmdhaW4gPSBvcHRpb25zLmdhaW4hO1xuICAgIGlmICgnUScgaW4gb3B0aW9ucykgdGhpcy5RID0gb3B0aW9ucy5RITtcbiAgICBpZiAoJ2ZpbHRlcicgaW4gb3B0aW9ucykgdGhpcy5iaXF1YWRGaWx0ZXIgPSBvcHRpb25zLmZpbHRlciE7XG5cbiAgICBpZiAodGhpcy5iaXF1YWRGaWx0ZXIgIT0gbnVsbCkge1xuICAgICAgdGhpcy5iaXF1YWQgPSBuZXcgQmlxdWFkRmlsdGVyKFxuICAgICAgICBDb2VmZmljaWVudHMuZnJvbShcbiAgICAgICAgICB0aGlzLmJpcXVhZEZpbHRlcixcbiAgICAgICAgICB0aGlzLnNhbXBsZVJhdGUsXG4gICAgICAgICAgdGhpcy5jdXRvZmYsXG4gICAgICAgICAgdGhpcy5RLFxuICAgICAgICAgIHRoaXMuZ2FpblxuICAgICAgICApXG4gICAgICApO1xuICAgIH1cblxuICAgIHRoaXMub25VcGRhdGU/LigpO1xuICB9XG5cbiAgcHVibGljIHNldEZpbHRlcihmaWx0ZXI6IEJpcXVhZEZpbHRlcnMpIHtcbiAgICB0aGlzLnVwZGF0ZSh7IGZpbHRlciB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRRKFE6IG51bWJlcikge1xuICAgIHRoaXMudXBkYXRlKHsgUSB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRDdXRvZmYoZjA6IG51bWJlcikge1xuICAgIHRoaXMudXBkYXRlKHsgY3V0b2ZmOiBmMCB9KTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRHYWluKGRCOiBudW1iZXIpIHtcbiAgICB0aGlzLnVwZGF0ZSh7IGdhaW46IGRCIH0pO1xuICB9XG5cbiAgcHVibGljIF90cmFuc2Zvcm0oXG4gIGNodW5rOiBCdWZmZXIsXG4gIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyxcbiAgY2FsbGJhY2s6IFRyYW5zZm9ybUNhbGxiYWNrKVxuICB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgIXRoaXMuYmlxdWFkKSB7XG4gICAgICB0aGlzLnB1c2goY2h1bmspO1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgY29uc3QgZW5kSW5kZXggPSBNYXRoLmZsb29yKGNodW5rLmxlbmd0aCAvIDIpICogMjtcbiAgICBjb25zdCB7IGJ5dGVzIH0gPSB0aGlzO1xuXG4gICAgZm9yIChsZXQgc2FtcGxlSW5kZXggPSAwOyBzYW1wbGVJbmRleCA8IGVuZEluZGV4OyBzYW1wbGVJbmRleCArPSBieXRlcykge1xuICAgICAgY29uc3QgaW50ID0gdGhpcy5fcmVhZEludChjaHVuaywgc2FtcGxlSW5kZXgpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5iaXF1YWQucnVuKGludCk7XG4gICAgICB0aGlzLl93cml0ZUludChjaHVuaywgdGhpcy5jbGFtcChyZXN1bHQpLCBzYW1wbGVJbmRleCk7XG4gICAgfVxuXG4gICAgdGhpcy5wdXNoKGNodW5rKTtcbiAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgfVxufSIsICJpbXBvcnQgeyBFcXVhbGl6ZXIgfSBmcm9tICcuL0VxdWFsaXplcic7XG5cbmV4cG9ydCB0eXBlIFJlYWRJbnRDYWxsYmFjayA9IChidWZmZXI6IEJ1ZmZlciwgaW5kZXg6IG51bWJlcikgPT4gbnVtYmVyO1xuZXhwb3J0IHR5cGUgV3JpdGVJbnRDYWxsYmFjayA9IChcbmJ1ZmZlcjogQnVmZmVyLFxuaW50OiBudW1iZXIsXG5pbmRleDogbnVtYmVyKVxuPT4gbnVtYmVyO1xuXG5leHBvcnQgY2xhc3MgQ2hhbm5lbFByb2Nlc3NvciB7XG4gIHB1YmxpYyBoaXN0b3J5OiBudW1iZXJbXTtcbiAgcHVibGljIGJhbmRNdWx0aXBsaWVyczogbnVtYmVyW107XG4gIHB1YmxpYyBjdXJyZW50OiBudW1iZXI7XG4gIHB1YmxpYyBtMTogbnVtYmVyO1xuICBwdWJsaWMgbTI6IG51bWJlcjtcblxuICBwdWJsaWMgY29uc3RydWN0b3IoYmFuZE11bHRpcGxpZXJzOiBudW1iZXJbXSkge1xuICAgIHRoaXMuaGlzdG9yeSA9IG5ldyBBcnJheShFcXVhbGl6ZXIuQkFORF9DT1VOVCAqIDYpLmZpbGwoMCk7XG4gICAgdGhpcy5iYW5kTXVsdGlwbGllcnMgPSBiYW5kTXVsdGlwbGllcnM7XG4gICAgdGhpcy5jdXJyZW50ID0gMDtcbiAgICB0aGlzLm0xID0gMjtcbiAgICB0aGlzLm0yID0gMTtcbiAgfVxuXG4gIHB1YmxpYyBwcm9jZXNzSW50KGludDogbnVtYmVyKSB7XG4gICAgbGV0IHJlc3VsdCA9IGludCAqIDAuMjU7XG5cbiAgICBmb3IgKGxldCBiYW5kSW5kZXggPSAwOyBiYW5kSW5kZXggPCBFcXVhbGl6ZXIuQkFORF9DT1VOVDsgYmFuZEluZGV4KyspIHtcbiAgICAgIGNvbnN0IHggPSBiYW5kSW5kZXggKiA2O1xuICAgICAgY29uc3QgeSA9IHggKyAzO1xuXG4gICAgICBjb25zdCBjb2VmZmljaWVudHMgPSBFcXVhbGl6ZXIuQ29lZmZpY2llbnRzNDgwMDBbYmFuZEluZGV4XTtcblxuICAgICAgY29uc3QgYmFuZFJlc3VsdCA9XG4gICAgICBjb2VmZmljaWVudHMuYWxwaGEgKiAoaW50IC0gdGhpcy5oaXN0b3J5W3ggKyB0aGlzLm0yXSkgK1xuICAgICAgY29lZmZpY2llbnRzLmdhbW1hICogdGhpcy5oaXN0b3J5W3kgKyB0aGlzLm0xXSAtXG4gICAgICBjb2VmZmljaWVudHMuYmV0YSAqIHRoaXMuaGlzdG9yeVt5ICsgdGhpcy5tMl07XG5cbiAgICAgIHRoaXMuaGlzdG9yeVt4ICsgdGhpcy5jdXJyZW50XSA9IGludDtcbiAgICAgIHRoaXMuaGlzdG9yeVt5ICsgdGhpcy5jdXJyZW50XSA9IGJhbmRSZXN1bHQ7XG5cbiAgICAgIHJlc3VsdCArPSBiYW5kUmVzdWx0ICogdGhpcy5iYW5kTXVsdGlwbGllcnNbYmFuZEluZGV4XTtcbiAgICB9XG5cbiAgICBjb25zdCB2YWwgPSByZXN1bHQgKiA0LjA7XG5cbiAgICByZXR1cm4gdmFsO1xuICB9XG5cbiAgcHVibGljIHByb2Nlc3MoXG4gIHNhbXBsZXM6IEJ1ZmZlcixcbiAgZXh0cmVtdW0gPSAxMzEwNzIsXG4gIGJ5dGVzID0gMixcbiAgcmVhZEludD86IFJlYWRJbnRDYWxsYmFjayxcbiAgd3JpdGVJbnQ/OiBXcml0ZUludENhbGxiYWNrKVxuICB7XG4gICAgY29uc3QgZW5kSW5kZXggPSBNYXRoLmZsb29yKHNhbXBsZXMubGVuZ3RoIC8gMikgKiAyO1xuICAgIGZvciAobGV0IHNhbXBsZUluZGV4ID0gMDsgc2FtcGxlSW5kZXggPCBlbmRJbmRleDsgc2FtcGxlSW5kZXggKz0gYnl0ZXMpIHtcbiAgICAgIGNvbnN0IHNhbXBsZSA9XG4gICAgICByZWFkSW50Py4oc2FtcGxlcywgc2FtcGxlSW5kZXgpID8/IHNhbXBsZXMucmVhZEludDE2TEUoc2FtcGxlSW5kZXgpO1xuICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5wcm9jZXNzSW50KHNhbXBsZSk7XG5cbiAgICAgIGNvbnN0IHZhbCA9IE1hdGgubWluKGV4dHJlbXVtIC0gMSwgTWF0aC5tYXgoLWV4dHJlbXVtLCByZXN1bHQpKTtcbiAgICAgIHdyaXRlSW50Py4oc2FtcGxlcywgdmFsLCBzYW1wbGVJbmRleCkgPz9cbiAgICAgIHNhbXBsZXMud3JpdGVJbnQxNkxFKHZhbCwgc2FtcGxlSW5kZXgpO1xuXG4gICAgICB0aGlzLnN0ZXAoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gc2FtcGxlcztcbiAgfVxuXG4gIHB1YmxpYyBzdGVwKCkge1xuICAgIGlmICgrK3RoaXMuY3VycmVudCA9PT0gMykge1xuICAgICAgdGhpcy5jdXJyZW50ID0gMDtcbiAgICB9XG5cbiAgICBpZiAoKyt0aGlzLm0xID09PSAzKSB7XG4gICAgICB0aGlzLm0xID0gMDtcbiAgICB9XG5cbiAgICBpZiAoKyt0aGlzLm0yID09PSAzKSB7XG4gICAgICB0aGlzLm0yID0gMDtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgcmVzZXQoKSB7XG4gICAgdGhpcy5oaXN0b3J5LmZpbGwoMC4wKTtcbiAgfVxufSIsICJleHBvcnQgY2xhc3MgRXF1YWxpemVyQ29lZmZpY2llbnRzIHtcbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICBwdWJsaWMgYmV0YTogbnVtYmVyLFxuICBwdWJsaWMgYWxwaGE6IG51bWJlcixcbiAgcHVibGljIGdhbW1hOiBudW1iZXIpXG4gIHt9XG5cbiAgcHVibGljIHNldEJldGEodjogbnVtYmVyKSB7XG4gICAgdGhpcy5iZXRhID0gdjtcbiAgfVxuXG4gIHB1YmxpYyBzZXRBbHBoYSh2OiBudW1iZXIpIHtcbiAgICB0aGlzLmFscGhhID0gdjtcbiAgfVxuXG4gIHB1YmxpYyBzZXRHYW1tYSh2OiBudW1iZXIpIHtcbiAgICB0aGlzLmdhbW1hID0gdjtcbiAgfVxuXG4gIHB1YmxpYyB0b0pTT04oKSB7XG4gICAgY29uc3QgeyBhbHBoYSwgYmV0YSwgZ2FtbWEgfSA9IHRoaXM7XG5cbiAgICByZXR1cm4geyBhbHBoYSwgYmV0YSwgZ2FtbWEgfTtcbiAgfVxufSIsICJleHBvcnQgY2xhc3MgRXF1YWxpemVyQ29uZmlndXJhdGlvbiB7XG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwdWJsaWMgYmFuZE11bHRpcGxpZXJzOiBudW1iZXJbXSkge31cblxuICBwdWJsaWMgc2V0R2FpbihiYW5kOiBudW1iZXIsIHZhbHVlOiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5pc1ZhbGlkQmFuZChiYW5kKSkge1xuICAgICAgdGhpcy5iYW5kTXVsdGlwbGllcnNbYmFuZF0gPSBNYXRoLm1heChNYXRoLm1pbih2YWx1ZSwgMS4wKSwgLTAuMjUpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBnZXRHYWluKGJhbmQ6IG51bWJlcikge1xuICAgIGlmICh0aGlzLmlzVmFsaWRCYW5kKGJhbmQpKSB7XG4gICAgICByZXR1cm4gdGhpcy5iYW5kTXVsdGlwbGllcnNbYmFuZF07XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAwLjA7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGlzVmFsaWRCYW5kKGJhbmQ6IG51bWJlcikge1xuICAgIHJldHVybiBiYW5kID49IDAgJiYgYmFuZCA8IHRoaXMuYmFuZE11bHRpcGxpZXJzLmxlbmd0aDtcbiAgfVxufSIsICJpbXBvcnQge1xuICBDaGFubmVsUHJvY2Vzc29yLFxuICBSZWFkSW50Q2FsbGJhY2ssXG4gIFdyaXRlSW50Q2FsbGJhY2sgfSBmcm9tXG4nLi9DaGFubmVsUHJvY2Vzc29yJztcbmltcG9ydCB7IEVxdWFsaXplckNvZWZmaWNpZW50cyB9IGZyb20gJy4vQ29lZmZpY2llbnRzJztcbmltcG9ydCB7IEVxdWFsaXplckNvbmZpZ3VyYXRpb24gfSBmcm9tICcuL0VxdWFsaXplckNvbmZpZ3VyYXRpb24nO1xuXG5leHBvcnQgaW50ZXJmYWNlIENoYW5uZWxQcm9jZXNzb3JJbnB1dCB7XG4gIGRhdGE6IEJ1ZmZlcjtcbiAgcmVhZEludD86IFJlYWRJbnRDYWxsYmFjaztcbiAgd3JpdGVJbnQ/OiBXcml0ZUludENhbGxiYWNrO1xuICBleHRyZW11bT86IG51bWJlcjtcbiAgYnl0ZXM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBFcXVhbGl6ZXIgZXh0ZW5kcyBFcXVhbGl6ZXJDb25maWd1cmF0aW9uIHtcbiAgcHVibGljIHN0YXRpYyBCQU5EX0NPVU5UID0gMTUgYXMgY29uc3Q7XG4gIHB1YmxpYyBzdGF0aWMgU0FNUExFX1JBVEUgPSA0ODAwMCBhcyBjb25zdDtcbiAgcHVibGljIHN0YXRpYyBDb2VmZmljaWVudHM0ODAwMCA9IFtcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5Ljk4NDc1NDY2NjRlLTEsIDcuNjIyNjY2ODE0M2UtNCwgMS45OTg0NjQ3NjU2KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5Ljk3NTYxODQ2NTRlLTEsIDEuMjE5MDc2NzI4OWUtMywgMS45OTc1MzQ0NjQ1KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5Ljk2MTYyNjEzNzllLTEsIDEuOTE4NjkzMTA0MWUtMywgMS45OTYwOTQ3MzY5KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5LjkzOTE1Nzg1NDNlLTEsIDMuMDQyMTA3Mjg2NWUtMywgMS45OTM3NDQ5NjE4KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5LjkwMjgzMDcyMTVlLTEsIDQuODU4NDYzOTI0MmUtMywgMS45ODk4NDY1NzAyKSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5Ljg0ODU4OTcyNjRlLTEsIDcuNTcwNTEzNjc5NWUtMywgMS45ODM3OTYyNTQzKSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5Ljc1ODg1MTI2NTdlLTEsIDEuMjA1NzQzNjcxNWUtMiwgMS45NzMxNzcyNDQ3KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5LjYyMjg1MjE4MTRlLTEsIDEuODg1NzM5MDkyOGUtMiwgMS45NTU2MTY0Njk0KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5LjQwODA5MzMxMzJlLTEsIDIuOTU5NTMzNDMzOGUtMiwgMS45MjQyMDU0Mzg0KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg5LjA3MDIwNTkxOTZlLTEsIDQuNjQ4OTcwNDAyMmUtMiwgMS44NjUzNDc2MTY2KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg4LjU4NjgwMDQyODllLTEsIDcuMDY1OTk3ODU1M2UtMiwgMS43NjAwNDAxMzM3KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg3Ljg0MDk2MTA3ODhlLTEsIDEuMDc5NTE5NDYwNmUtMSwgMS41NDUwNzI1NTIyKSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyg2LjgzMzI4NjEwMDJlLTEsIDEuNTgzMzU2OTQ5OWUtMSwgMS4xNDI2NDQ3MTU1KSxcbiAgbmV3IEVxdWFsaXplckNvZWZmaWNpZW50cyhcbiAgICA1LjUyNjc1MTgyMjhlLTEsXG4gICAgMi4yMzY2MjQwODg2ZS0xLFxuICAgIDQuMDE4NjE5MDgwM2UtMVxuICApLFxuICBuZXcgRXF1YWxpemVyQ29lZmZpY2llbnRzKFxuICAgIDQuMTgxMTg4ODQ0N2UtMSxcbiAgICAyLjkwOTQwNTU3NzdlLTEsXG4gICAgLTcuMDkwNTk0NDIyM2UtMVxuICApXTtcblxuICBwdWJsaWMgY2hhbm5lbHM6IENoYW5uZWxQcm9jZXNzb3JbXSA9IFtdO1xuICBwdWJsaWMgY2hhbm5lbENvdW50OiBudW1iZXI7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKGNoYW5uZWxDb3VudDogbnVtYmVyLCBiYW5kTXVsdGlwbGllcnM6IG51bWJlcltdKSB7XG4gICAgc3VwZXIoYmFuZE11bHRpcGxpZXJzKTtcbiAgICB0aGlzLmNoYW5uZWxDb3VudCA9IGNoYW5uZWxDb3VudDtcbiAgICB0aGlzLmNoYW5uZWxzID0gdGhpcy5jcmVhdGVDaGFubmVsUHJvY2Vzc29yKCk7XG4gIH1cblxuICBwdWJsaWMgY3JlYXRlQ2hhbm5lbFByb2Nlc3NvcigpIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh7IGxlbmd0aDogdGhpcy5jaGFubmVsQ291bnQgfSwgKCkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBDaGFubmVsUHJvY2Vzc29yKHRoaXMuYmFuZE11bHRpcGxpZXJzKTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyBwcm9jZXNzKGlucHV0OiBDaGFubmVsUHJvY2Vzc29ySW5wdXRbXSkge1xuICAgIHJldHVybiB0aGlzLmNoYW5uZWxzLm1hcCgoYywgaSkgPT4ge1xuICAgICAgY29uc3QgeyBkYXRhLCBleHRyZW11bSwgcmVhZEludCwgd3JpdGVJbnQsIGJ5dGVzIH0gPSBpbnB1dFtpXTtcblxuICAgICAgcmV0dXJuIGMucHJvY2VzcyhkYXRhLCBleHRyZW11bSwgYnl0ZXMsIHJlYWRJbnQsIHdyaXRlSW50KTtcbiAgICB9KTtcbiAgfVxufSIsICJpbXBvcnQgeyBUcmFuc2Zvcm1DYWxsYmFjayB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBQQ01UcmFuc2Zvcm1lciwgUENNVHJhbnNmb3JtZXJPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IHsgRXF1YWxpemVyIH0gZnJvbSAnLi9FcXVhbGl6ZXInO1xuXG5leHBvcnQgaW50ZXJmYWNlIEVxdWFsaXplclN0cmVhbU9wdGlvbnMgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lck9wdGlvbnMge1xuICBiYW5kTXVsdGlwbGllcj86IEVxdWFsaXplckJhbmRbXTtcbiAgY2hhbm5lbHM/OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRXF1YWxpemVyQmFuZCB7XG4gIGJhbmQ6IG51bWJlcjtcbiAgZ2FpbjogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgRXF1YWxpemVyU3RyZWFtIGV4dGVuZHMgUENNVHJhbnNmb3JtZXIge1xuICBwdWJsaWMgYmFuZE11bHRpcGxpZXJzOiBudW1iZXJbXSA9IG5ldyBBcnJheShFcXVhbGl6ZXIuQkFORF9DT1VOVCkuZmlsbCgwKTtcbiAgcHVibGljIGVxdWFsaXplcjogRXF1YWxpemVyO1xuICBwdWJsaWMgY29uc3RydWN0b3Iob3B0aW9ucz86IEVxdWFsaXplclN0cmVhbU9wdGlvbnMpIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIG9wdGlvbnMgPSBPYmplY3QuYXNzaWduKFxuICAgICAge30sXG4gICAgICB7XG4gICAgICAgIGJhbmRNdWx0aXBsaWVyOiBbXSxcbiAgICAgICAgY2hhbm5lbHM6IDFcbiAgICAgIH0sXG4gICAgICBvcHRpb25zIHx8IHt9XG4gICAgKTtcblxuICAgIHRoaXMuZXF1YWxpemVyID0gbmV3IEVxdWFsaXplcihvcHRpb25zLmNoYW5uZWxzIHx8IDEsIHRoaXMuYmFuZE11bHRpcGxpZXJzKTtcbiAgICBpZiAoQXJyYXkuaXNBcnJheShvcHRpb25zLmJhbmRNdWx0aXBsaWVyKSlcbiAgICB0aGlzLl9wcm9jZXNzQmFuZHMob3B0aW9ucy5iYW5kTXVsdGlwbGllcik7XG4gIH1cblxuICBwdWJsaWMgX3Byb2Nlc3NCYW5kcyhtdWx0aXBsaWVyOiBFcXVhbGl6ZXJCYW5kW10pIHtcbiAgICBmb3IgKGNvbnN0IG11bCBvZiBtdWx0aXBsaWVyKSB7XG4gICAgICBpZiAobXVsLmJhbmQgPiBFcXVhbGl6ZXIuQkFORF9DT1VOVCAtIDEgfHwgbXVsLmJhbmQgPCAwKVxuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoXG4gICAgICAgIGBCYW5kIHZhbHVlIG91dCBvZiByYW5nZS4gRXhwZWN0ZWQgPjAgJiA8JHtcbiAgICAgICAgRXF1YWxpemVyLkJBTkRfQ09VTlQgLSAxfSwgcmVjZWl2ZWQgXCIke1xuICAgICAgICBtdWwuYmFuZH1cImBcbiAgICAgICk7XG4gICAgICB0aGlzLmVxdWFsaXplci5zZXRHYWluKG11bC5iYW5kLCBtdWwuZ2Fpbik7XG4gICAgfVxuXG4gICAgdGhpcy5vblVwZGF0ZT8uKCk7XG4gIH1cblxuICBwdWJsaWMgX3RyYW5zZm9ybShcbiAgY2h1bms6IEJ1ZmZlcixcbiAgZW5jb2Rpbmc6IEJ1ZmZlckVuY29kaW5nLFxuICBjYWxsYmFjazogVHJhbnNmb3JtQ2FsbGJhY2spXG4gIDogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIHRoaXMucHVzaChjaHVuayk7XG4gICAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgICB9XG5cbiAgICB0aGlzLmVxdWFsaXplci5wcm9jZXNzKFtcbiAgICB7XG4gICAgICBkYXRhOiBjaHVuayxcbiAgICAgIGV4dHJlbXVtOiB0aGlzLmV4dHJlbXVtLFxuICAgICAgcmVhZEludDogKGIsIGlkeCkgPT4gdGhpcy5fcmVhZEludChiLCBpZHgpLFxuICAgICAgd3JpdGVJbnQ6IChiLCBpLCBpZHgpID0+IHRoaXMuX3dyaXRlSW50KGIsIGksIGlkeCksXG4gICAgICBieXRlczogdGhpcy5ieXRlc1xuICAgIH1dXG4gICAgKTtcblxuICAgIHRoaXMucHVzaChjaHVuayk7XG5cbiAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRFUSgpIHtcbiAgICByZXR1cm4gdGhpcy5iYW5kTXVsdGlwbGllcnMubWFwKChtLCBpKSA9PiAoe1xuICAgICAgYmFuZDogaSxcbiAgICAgIGdhaW46IG1cbiAgICB9KSkgYXMgRXF1YWxpemVyQmFuZFtdO1xuICB9XG5cbiAgcHVibGljIHNldEVRKGJhbmRzOiBFcXVhbGl6ZXJCYW5kW10pIHtcbiAgICB0aGlzLl9wcm9jZXNzQmFuZHMoYmFuZHMpO1xuICB9XG5cbiAgcHVibGljIHJlc2V0RVEoKSB7XG4gICAgdGhpcy5fcHJvY2Vzc0JhbmRzKFxuICAgICAgQXJyYXkuZnJvbShcbiAgICAgICAge1xuICAgICAgICAgIGxlbmd0aDogRXF1YWxpemVyLkJBTkRfQ09VTlRcbiAgICAgICAgfSxcbiAgICAgICAgKF8sIGkpID0+ICh7XG4gICAgICAgICAgYmFuZDogaSxcbiAgICAgICAgICBnYWluOiAwXG4gICAgICAgIH0pXG4gICAgICApXG4gICAgKTtcbiAgfVxufSIsICJpbXBvcnQgeyBUcmFuc2Zvcm1DYWxsYmFjayB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBQQ01UcmFuc2Zvcm1lciwgUENNVHJhbnNmb3JtZXJPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMnO1xuXG4vKlxuTW9ubzogWzAsIDEsIDIsIDMsIDQsIDVdXG5TdGVyZW86IFswLCAxLCAwLCAxLCAyLCAzLCAyLCAzLCA0LCA1LCA0LCA1XVxuKi9cblxuZXhwb3J0IHR5cGUgTVNUU3RyYXRlZ3kgPSAnbTJzJyB8ICdzMm0nO1xuXG5leHBvcnQgaW50ZXJmYWNlIE1vbm9TdGVyZW9UcmFuc2Zvcm1lck9wdGlvbnMgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lck9wdGlvbnMge1xuICBzdHJhdGVneTogTVNUU3RyYXRlZ3k7XG59XG5cbmV4cG9ydCBjbGFzcyBNb25vU3RlcmVvVHJhbnNmb3JtZXIgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lciB7XG4gIHB1YmxpYyBzdHJhdGVneTogTVNUU3RyYXRlZ3k7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM/OiBNb25vU3RlcmVvVHJhbnNmb3JtZXJPcHRpb25zKSB7XG4gICAgc3VwZXIob3B0aW9ucyk7XG4gICAgaWYgKCFbJ20ycycsICdzMm0nXS5pbmNsdWRlcyhvcHRpb25zPy5zdHJhdGVneSBhcyBNU1RTdHJhdGVneSkpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYFN0cmF0ZWd5IG11c3QgYmUgXCJtMnNcIiBvciBcInMybVwiYCk7XG4gICAgfVxuXG4gICAgdGhpcy5zdHJhdGVneSA9IG9wdGlvbnMhLnN0cmF0ZWd5O1xuICB9XG5cbiAgcHVibGljIHNldFN0cmF0ZWd5KHN0cmF0ZWd5OiBNU1RTdHJhdGVneSkge1xuICAgIHRoaXMuc3RyYXRlZ3kgPSBzdHJhdGVneTtcbiAgfVxuXG4gIHB1YmxpYyBfdHJhbnNmb3JtKFxuICBjaHVuazogQnVmZmVyLFxuICBlbmNvZGluZzogQnVmZmVyRW5jb2RpbmcsXG4gIGNhbGxiYWNrOiBUcmFuc2Zvcm1DYWxsYmFjaylcbiAgOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkge1xuICAgICAgdGhpcy5wdXNoKGNodW5rKTtcbiAgICAgIHJldHVybiBjYWxsYmFjaygpO1xuICAgIH1cblxuICAgIGNvbnN0IGxlbiA9IE1hdGguZmxvb3IoY2h1bmsubGVuZ3RoIC8gMikgKiAyO1xuXG4gICAgaWYgKHRoaXMuc3RyYXRlZ3kgPT09ICdtMnMnKSB7XG4gICAgICB0aGlzLnB1c2godGhpcy50b1N0ZXJlbyhjaHVuaywgbGVuKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHVzaCh0aGlzLnRvTW9ubyhjaHVuaywgbGVuKSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwdWJsaWMgdG9TdGVyZW8oc2FtcGxlOiBCdWZmZXIsIGxlbjogbnVtYmVyKSB7XG4gICAgY29uc3QgYnl0ZXMgPSB0aGlzLmJ5dGVzO1xuICAgIGNvbnN0IHN0ZXJlb0J1ZmZlciA9IEJ1ZmZlci5hbGxvYyhsZW4gKiAyKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpICs9IGJ5dGVzKSB7XG4gICAgICBzdGVyZW9CdWZmZXJbaSAqIDIgKyAwXSA9IHNhbXBsZVtpXTtcbiAgICAgIHN0ZXJlb0J1ZmZlcltpICogMiArIDFdID0gc2FtcGxlW2kgKyAxXTtcbiAgICAgIHN0ZXJlb0J1ZmZlcltpICogMiArIDJdID0gc2FtcGxlW2ldO1xuICAgICAgc3RlcmVvQnVmZmVyW2kgKiAyICsgM10gPSBzYW1wbGVbaSArIDFdO1xuICAgIH1cblxuICAgIHJldHVybiBzdGVyZW9CdWZmZXI7XG4gIH1cblxuICBwdWJsaWMgdG9Nb25vKHNhbXBsZTogQnVmZmVyLCBsZW46IG51bWJlcikge1xuICAgIGNvbnN0IGJ5dGVzID0gdGhpcy5ieXRlcztcbiAgICBjb25zdCBtb25vQnVmZmVyID0gQnVmZmVyLmFsbG9jKE1hdGguZmxvb3IobGVuIC8gMikpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZW47IGkgKz0gYnl0ZXMpIHtcbiAgICAgIG1vbm9CdWZmZXJbaV0gPSBzYW1wbGVbaSAqIDIgKyAwXTtcbiAgICAgIG1vbm9CdWZmZXJbaSArIDFdID0gc2FtcGxlW2kgKiAyICsgMV07XG4gICAgfVxuXG4gICAgcmV0dXJuIG1vbm9CdWZmZXI7XG4gIH1cbn0iLCAiZXhwb3J0ICogZnJvbSAnLi9iaXF1YWQnO1xuZXhwb3J0ICogZnJvbSAnLi9kc3AnO1xuZXhwb3J0ICogZnJvbSAnLi9lcXVhbGl6ZXInOyIsICJpbXBvcnQgeyBCaXF1YWRGaWx0ZXIsIEJpcXVhZEZpbHRlcnMsIENvZWZmaWNpZW50cyB9IGZyb20gJy4uLy4uL2JpcXVhZCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQUZCaXF1YWRDb25maWcge1xuICBiaXF1YWQ6IEJpcXVhZEZpbHRlcjtcbiAgc2FtcGxlOiBudW1iZXI7XG4gIGN1dG9mZjogbnVtYmVyO1xuICBnYWluOiBudW1iZXI7XG4gIGZpbHRlcjogQmlxdWFkRmlsdGVycztcbiAgY29lZmZpY2llbnQ6IENvZWZmaWNpZW50cztcbiAgUTogbnVtYmVyO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlCaXF1YWQoZmlsdGVyZXI6IEJpcXVhZEZpbHRlciwgaW50OiBudW1iZXIpIHtcbiAgcmV0dXJuIGZpbHRlcmVyLnJ1bihpbnQpO1xufSIsICJleHBvcnQgaW50ZXJmYWNlIEFGUHVsc2F0b3JDb25maWcge1xuICBoejogbnVtYmVyO1xuICB4OiBudW1iZXI7XG4gIGRJOiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQUZUcmVtb2xvQ29uZmlnIHtcbiAgcGhhc2U6IG51bWJlcjtcbiAgZGVwdGg6IG51bWJlcjtcbiAgZnJlcXVlbmN5OiBudW1iZXI7XG59XG5cbmV4cG9ydCB0eXBlIEFGVmlicmF0b0NvbmZpZyA9IEFGVHJlbW9sb0NvbmZpZztcblxuZXhwb3J0IHR5cGUgTFIgPSAwIHwgMTtcblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5UHVsc2F0b3IoXG5jb25maWc6IEFGUHVsc2F0b3JDb25maWcsXG5pbnQ6IG51bWJlcixcbmNoYW5uZWw6IExSKVxue1xuICBjb25zdCBzaW4gPSBNYXRoLnNpbihjb25maWcueCk7XG4gIGNvbnN0IGN1cnJlbnRDaGFubmVsVmFsID0gY2hhbm5lbCA9PT0gMCA/IHNpbiA6IC1zaW47XG4gIGNvbnN0IHJlcyA9IGludCAqIChjdXJyZW50Q2hhbm5lbFZhbCArIDEuMCkgLyAyLjA7XG5cbiAgY29uZmlnLnggKz0gY29uZmlnLmRJO1xuXG4gIHJldHVybiByZXM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVRyZW1vbG8oXG5jb25maWc6IEFGVHJlbW9sb0NvbmZpZyxcbmludDogbnVtYmVyLFxuc2FtcGxlUmF0ZTogbnVtYmVyKVxue1xuICBjb25zdCBmT2Zmc2V0ID0gMS4wIC0gY29uZmlnLmRlcHRoO1xuICBjb25zdCBtb2RTaWduYWwgPSBmT2Zmc2V0ICsgY29uZmlnLmRlcHRoICogTWF0aC5zaW4oY29uZmlnLnBoYXNlKTtcbiAgY29uZmlnLnBoYXNlICs9IDIgKiBNYXRoLlBJIC8gc2FtcGxlUmF0ZSAqIGNvbmZpZy5mcmVxdWVuY3k7XG4gIHJldHVybiBtb2RTaWduYWwgKiBpbnQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBhcHBseVZpYnJhdG8oXG5jb25maWc6IEFGVmlicmF0b0NvbmZpZyxcbmludDogbnVtYmVyLFxuc2FtcGxlUmF0ZTogbnVtYmVyKVxue1xuICBjb25zdCBmT2Zmc2V0ID0gMS4wIC0gY29uZmlnLmRlcHRoO1xuICBjb25zdCBtb2RTaWduYWwgPVxuICBmT2Zmc2V0ICsgY29uZmlnLmRlcHRoICogTWF0aC5zaW4oMiAqIE1hdGguUEkgKiBjb25maWcucGhhc2UpO1xuICBjb25maWcucGhhc2UgKz0gMiAqIE1hdGguUEkgLyBzYW1wbGVSYXRlICogY29uZmlnLmZyZXF1ZW5jeTtcbiAgcmV0dXJuIG1vZFNpZ25hbCAqIGludDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGFwcGx5Vm9sdW1lKHZvbDogbnVtYmVyLCBpbnQ6IG51bWJlcikge1xuICByZXR1cm4gdm9sICogaW50O1xufSIsICJpbXBvcnQgeyBFcXVhbGl6ZXIgfSBmcm9tICcuLi8uLi9lcXVhbGl6ZXInO1xuXG5leHBvcnQgZnVuY3Rpb24gYXBwbHlFcXVhbGl6YXRpb24oZXE6IEVxdWFsaXplciwgaW50OiBudW1iZXIpIHtcbiAgY29uc3QgcHJvY2Vzc29yID0gZXEuY2hhbm5lbHNbMF07XG4gIGNvbnN0IHJlc3VsdCA9IHByb2Nlc3Nvci5wcm9jZXNzSW50KGludCk7XG4gIHByb2Nlc3Nvci5zdGVwKCk7XG4gIHJldHVybiByZXN1bHQ7XG59IiwgImltcG9ydCB7IFRyYW5zZm9ybUNhbGxiYWNrIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCB7IFBDTVRyYW5zZm9ybWVyLCBQQ01UcmFuc2Zvcm1lck9wdGlvbnMgfSBmcm9tICcuLi91dGlscyc7XG5pbXBvcnQge1xuICBBRlB1bHNhdG9yQ29uZmlnLFxuICBBRlRyZW1vbG9Db25maWcsXG4gIEFGVmlicmF0b0NvbmZpZyxcbiAgTFIsXG4gIGFwcGx5UHVsc2F0b3IsXG4gIGFwcGx5VHJlbW9sbyxcbiAgYXBwbHlWaWJyYXRvIH0gZnJvbVxuJy4vdHJhbnNmb3JtZXJzJztcbmltcG9ydCB7IEVxdWFsaXplckJhbmQgfSBmcm9tICcuLi9lcXVhbGl6ZXInO1xuXG5leHBvcnQgY29uc3QgQXVkaW9GaWx0ZXJzID0ge1xuICAnOEQnOiAnOEQnLFxuICBUcmVtb2xvOiAnVHJlbW9sbycsXG4gIFZpYnJhdG86ICdWaWJyYXRvJ1xufSBhcyBjb25zdDtcblxuZXhwb3J0IHR5cGUgUENNRmlsdGVycyA9IGtleW9mIHR5cGVvZiBBdWRpb0ZpbHRlcnM7XG5cbmV4cG9ydCBpbnRlcmZhY2UgUENNRmlsdGVyZXJPcHRpb25zIGV4dGVuZHMgUENNVHJhbnNmb3JtZXJPcHRpb25zIHtcbiAgZmlsdGVycz86IFBDTUZpbHRlcnNbXTtcbn1cblxuZXhwb3J0IGNvbnN0IEFGX05JR0hUQ09SRV9SQVRFID0gMS4zIGFzIGNvbnN0O1xuZXhwb3J0IGNvbnN0IEFGX1ZBUE9SV0FWRV9SQVRFID0gMC44IGFzIGNvbnN0O1xuXG5leHBvcnQgY29uc3QgQkFTU19FUV9CQU5EUzogRXF1YWxpemVyQmFuZFtdID0gQXJyYXkuZnJvbShcbiAgeyBsZW5ndGg6IDMgfSxcbiAgKF8sIGkpID0+ICh7XG4gICAgYmFuZDogaSxcbiAgICBnYWluOiAwLjI1XG4gIH0pXG4pO1xuXG4vLyBiYXNlZCBvbiBsYXZhZHNwXG5leHBvcnQgY2xhc3MgQXVkaW9GaWx0ZXIgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lciB7XG4gIHB1YmxpYyBmaWx0ZXJzOiBQQ01GaWx0ZXJzW10gPSBbXTtcbiAgcHVibGljIHRhcmdldFNhbXBsZVJhdGUgPSB0aGlzLnNhbXBsZVJhdGU7XG5cbiAgcHVibGljIHB1bHNhdG9yQ29uZmlnOiBBRlB1bHNhdG9yQ29uZmlnID0ge1xuICAgIGh6OiAwLjAyLFxuICAgIHg6IDAsXG4gICAgZEk6IDAuMDAwMDAzOTI2OTkwODE2OTg3MjQxXG4gIH07XG5cbiAgcHVibGljIHRyZW1vbG9Db25maWc6IEFGVHJlbW9sb0NvbmZpZyA9IHtcbiAgICBwaGFzZTogMCxcbiAgICBkZXB0aDogMC41LFxuICAgIGZyZXF1ZW5jeTogNS4wXG4gIH07XG5cbiAgcHVibGljIHZpYnJhdG9Db25maWc6IEFGVmlicmF0b0NvbmZpZyA9IHtcbiAgICBwaGFzZTogMCxcbiAgICBkZXB0aDogMC41LFxuICAgIGZyZXF1ZW5jeTogNS4wXG4gIH07XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKG9wdGlvbnM/OiBQQ01GaWx0ZXJlck9wdGlvbnMpIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIGlmIChvcHRpb25zICYmIEFycmF5LmlzQXJyYXkob3B0aW9ucy5maWx0ZXJzKSkge1xuICAgICAgdGhpcy5zZXRGaWx0ZXJzKG9wdGlvbnMuZmlsdGVycyk7XG4gICAgfVxuXG4gICAgdGhpcy5vblVwZGF0ZT8uKCk7XG4gIH1cblxuICBwdWJsaWMgc2V0VGFyZ2V0U2FtcGxlUmF0ZShyYXRlOiBudW1iZXIpIHtcbiAgICB0aGlzLnRhcmdldFNhbXBsZVJhdGUgPSByYXRlIHx8IHRoaXMuc2FtcGxlUmF0ZTtcbiAgICByZXR1cm47XG4gIH1cblxuICBwdWJsaWMgc2V0UHVsc2F0b3IoaHo6IG51bWJlcikge1xuICAgIGh6IC89IDQ7IC8vIG1hdGNoIGZmbXBlZ1xuICAgIHRoaXMucHVsc2F0b3JDb25maWcuaHogPSBoejtcbiAgICBjb25zdCBzYW1wbGVzUGVyQ3ljbGUgPSB0aGlzLnRhcmdldFNhbXBsZVJhdGUgLyAoaHogKiAyICogTWF0aC5QSSk7XG4gICAgdGhpcy5wdWxzYXRvckNvbmZpZy5kSSA9IGh6ID09PSAwID8gMCA6IDEgLyBzYW1wbGVzUGVyQ3ljbGU7XG5cbiAgICB0aGlzLm9uVXBkYXRlPy4oKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgcHVsc2F0b3IoKSB7XG4gICAgcmV0dXJuIHRoaXMucHVsc2F0b3JDb25maWcuaHo7XG4gIH1cblxuICBwdWJsaWMgc2V0VHJlbW9sbyh7XG4gICAgZGVwdGggPSB0aGlzLnRyZW1vbG9Db25maWcuZGVwdGgsXG4gICAgZnJlcXVlbmN5ID0gdGhpcy50cmVtb2xvQ29uZmlnLmZyZXF1ZW5jeSxcbiAgICBwaGFzZSA9IHRoaXMudHJlbW9sb0NvbmZpZy5waGFzZVxuICB9OiBQYXJ0aWFsPEFGVHJlbW9sb0NvbmZpZz4pIHtcbiAgICBpZiAodHlwZW9mIGRlcHRoID09PSAnbnVtYmVyJykgdGhpcy50cmVtb2xvQ29uZmlnLmRlcHRoID0gZGVwdGg7XG4gICAgaWYgKHR5cGVvZiBmcmVxdWVuY3kgPT09ICdudW1iZXInKSB0aGlzLnRyZW1vbG9Db25maWcuZnJlcXVlbmN5ID0gZnJlcXVlbmN5O1xuICAgIGlmICh0eXBlb2YgcGhhc2UgPT09ICdudW1iZXInKSB0aGlzLnRyZW1vbG9Db25maWcucGhhc2UgPSBwaGFzZTtcblxuICAgIHRoaXMub25VcGRhdGU/LigpO1xuICB9XG5cbiAgcHVibGljIHNldFZpYnJhdG8oe1xuICAgIGRlcHRoID0gdGhpcy52aWJyYXRvQ29uZmlnLmRlcHRoLFxuICAgIGZyZXF1ZW5jeSA9IHRoaXMudmlicmF0b0NvbmZpZy5mcmVxdWVuY3ksXG4gICAgcGhhc2UgPSB0aGlzLnZpYnJhdG9Db25maWcucGhhc2VcbiAgfTogUGFydGlhbDxBRlZpYnJhdG9Db25maWc+KSB7XG4gICAgaWYgKHR5cGVvZiBkZXB0aCA9PT0gJ251bWJlcicpIHRoaXMudmlicmF0b0NvbmZpZy5kZXB0aCA9IGRlcHRoO1xuICAgIGlmICh0eXBlb2YgZnJlcXVlbmN5ID09PSAnbnVtYmVyJykgdGhpcy52aWJyYXRvQ29uZmlnLmZyZXF1ZW5jeSA9IGZyZXF1ZW5jeTtcbiAgICBpZiAodHlwZW9mIHBoYXNlID09PSAnbnVtYmVyJykgdGhpcy52aWJyYXRvQ29uZmlnLnBoYXNlID0gcGhhc2U7XG5cbiAgICB0aGlzLm9uVXBkYXRlPy4oKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdHJlbW9sbygpIHtcbiAgICByZXR1cm4gdGhpcy50cmVtb2xvQ29uZmlnO1xuICB9XG5cbiAgcHVibGljIHNldEZpbHRlcnMoZmlsdGVyczogUENNRmlsdGVyc1tdKSB7XG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGZpbHRlcnMpIHx8ICFmaWx0ZXJzLmV2ZXJ5KChyKSA9PiByIGluIEF1ZGlvRmlsdGVycykpIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICB0aGlzLmZpbHRlcnMgPSBmaWx0ZXJzO1xuXG4gICAgdGhpcy5vblVwZGF0ZT8uKCk7XG5cbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHB1YmxpYyBfdHJhbnNmb3JtKFxuICBjaHVuazogQnVmZmVyLFxuICBlbmNvZGluZzogQnVmZmVyRW5jb2RpbmcsXG4gIGNhbGxiYWNrOiBUcmFuc2Zvcm1DYWxsYmFjaylcbiAgOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCAhdGhpcy5maWx0ZXJzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKG51bGwsIGNodW5rKTtcbiAgICB9XG5cbiAgICBjb25zdCBsZW4gPSBNYXRoLmZsb29yKGNodW5rLmxlbmd0aCAvIDIpICogMjtcbiAgICBjb25zdCB7IGJ5dGVzIH0gPSB0aGlzO1xuXG4gICAgLy8gbGVmdC1yaWdodCBjaGFubmVsXG4gICAgbGV0IEwgPSBmYWxzZTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpICs9IGJ5dGVzKSB7XG4gICAgICBjb25zdCBpbnQgPSB0aGlzLl9yZWFkSW50KGNodW5rLCBpKTtcbiAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5hcHBseUZpbHRlcnMoaW50LCArKEwgPSAhTCkgYXMgTFIpO1xuICAgICAgdGhpcy5fd3JpdGVJbnQoY2h1bmssIHRoaXMuY2xhbXAodmFsdWUpLCBpKTtcbiAgICB9XG5cbiAgICB0aGlzLnB1c2goY2h1bmspO1xuXG4gICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0IGN1cnJlbnRTYW1wbGVSYXRlKCkge1xuICAgIHJldHVybiB0aGlzLnRhcmdldFNhbXBsZVJhdGUgfHwgdGhpcy5zYW1wbGVSYXRlO1xuICB9XG5cbiAgcHVibGljIGFwcGx5RmlsdGVycyhieXRlOiBudW1iZXIsIGNoYW5uZWw6IExSKSB7XG4gICAgaWYgKHRoaXMuZmlsdGVycy5sZW5ndGgpIHtcbiAgICAgIGZvciAoY29uc3QgZmlsdGVyIG9mIHRoaXMuZmlsdGVycykge1xuICAgICAgICBpZiAoZmlsdGVyID09PSAnOEQnKSB7XG4gICAgICAgICAgYnl0ZSA9IGFwcGx5UHVsc2F0b3IodGhpcy5wdWxzYXRvckNvbmZpZywgYnl0ZSwgY2hhbm5lbCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmlsdGVyID09PSAnVHJlbW9sbycpIHtcbiAgICAgICAgICBieXRlID0gYXBwbHlUcmVtb2xvKHRoaXMudHJlbW9sb0NvbmZpZywgYnl0ZSwgdGhpcy5jdXJyZW50U2FtcGxlUmF0ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZmlsdGVyID09PSAnVmlicmF0bycpIHtcbiAgICAgICAgICBieXRlID0gYXBwbHlWaWJyYXRvKHRoaXMudmlicmF0b0NvbmZpZywgYnl0ZSwgdGhpcy5jdXJyZW50U2FtcGxlUmF0ZSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gYnl0ZTtcbiAgfVxufSIsICJpbXBvcnQgeyBQQ01UcmFuc2Zvcm1lciwgUENNVHJhbnNmb3JtZXJPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBDTVJlc2FtcGxlck9wdGlvbnMgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lck9wdGlvbnMge1xuICBpbnB1dFNhbXBsZVJhdGU6IG51bWJlcjtcbiAgdGFyZ2V0U2FtcGxlUmF0ZTogbnVtYmVyO1xuICBjaGFubmVscz86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXNhbXBsZVBhcmFtZXRlcnMge1xuICBjdXJyZW50RmlsdGVyOiBDb21tb25SZXNhbXBsZXJGaWx0ZXJQcmVzZXQgfCBudWxsO1xuICBpbnB1dFNhbXBsZVJhdGU6IG51bWJlcjtcbiAgY2hhbm5lbHM6IG51bWJlcjtcbiAgc2FtcGxlUmF0ZTogbnVtYmVyO1xufVxuXG5leHBvcnQgdHlwZSBDb21tb25SZXNhbXBsZXJGaWx0ZXJQcmVzZXQgPSAnbmlnaHRjb3JlJyB8ICd2YXBvcndhdmUnO1xuXG5leHBvcnQgY2xhc3MgUENNUmVzYW1wbGVyIGV4dGVuZHMgUENNVHJhbnNmb3JtZXIge1xuICBwcml2YXRlIHJlYWRvbmx5IGlucHV0U2FtcGxlUmF0ZTogbnVtYmVyO1xuICBwcml2YXRlIHJlYWRvbmx5IGNoYW5uZWxzOiBudW1iZXI7XG4gIHByaXZhdGUgYnVmZmVyOiBCdWZmZXI7XG4gIHB1YmxpYyBjdXJyZW50RmlsdGVyOiBDb21tb25SZXNhbXBsZXJGaWx0ZXJQcmVzZXQgfCBudWxsID0gbnVsbDtcblxuICBwdWJsaWMgY29uc3RydWN0b3Iob3B0aW9ucz86IFBDTVJlc2FtcGxlck9wdGlvbnMpIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIHRoaXMuaW5wdXRTYW1wbGVSYXRlID0gb3B0aW9ucz8uaW5wdXRTYW1wbGVSYXRlID8/IDQ4MDAwO1xuICAgIHRoaXMuY2hhbm5lbHMgPSBvcHRpb25zPy5jaGFubmVscyA/PyAyO1xuICAgIHRoaXMuYnVmZmVyID0gQnVmZmVyLmFsbG9jKDApO1xuXG4gICAgaWYgKHRoaXMuaW5wdXRTYW1wbGVSYXRlIDwgMSkge1xuICAgICAgdGhpcy5pbnB1dFNhbXBsZVJhdGUgPSA0ODAwMDtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucz8udGFyZ2V0U2FtcGxlUmF0ZSkge1xuICAgICAgdGhpcy5zZXRTYW1wbGVSYXRlKG9wdGlvbnM/LnRhcmdldFNhbXBsZVJhdGUpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBzZXRGaWx0ZXIoZmlsdGVyOiBDb21tb25SZXNhbXBsZXJGaWx0ZXJQcmVzZXQgfCBudWxsKSB7XG4gICAgaWYgKHRoaXMuY3VycmVudEZpbHRlciA9PT0gZmlsdGVyKSByZXR1cm47XG5cbiAgICBzd2l0Y2ggKGZpbHRlcikge1xuICAgICAgY2FzZSAnbmlnaHRjb3JlJzpcbiAgICAgICAgdGhpcy5zZXRTYW1wbGVSYXRlKHRoaXMuaW5wdXRTYW1wbGVSYXRlICogMS4yNSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAndmFwb3J3YXZlJzpcbiAgICAgICAgdGhpcy5zZXRTYW1wbGVSYXRlKHRoaXMuaW5wdXRTYW1wbGVSYXRlICogMC44KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aGlzLnNldFNhbXBsZVJhdGUodGhpcy5pbnB1dFNhbXBsZVJhdGUpO1xuICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICB0aGlzLmN1cnJlbnRGaWx0ZXIgPSBmaWx0ZXI7XG4gIH1cblxuICBwdWJsaWMgZ2V0UGFyYW1ldGVycygpOiBSZXNhbXBsZVBhcmFtZXRlcnMge1xuICAgIHJldHVybiB7XG4gICAgICBjdXJyZW50RmlsdGVyOiB0aGlzLmN1cnJlbnRGaWx0ZXIsXG4gICAgICBpbnB1dFNhbXBsZVJhdGU6IHRoaXMuaW5wdXRTYW1wbGVSYXRlLFxuICAgICAgY2hhbm5lbHM6IHRoaXMuY2hhbm5lbHMsXG4gICAgICBzYW1wbGVSYXRlOiB0aGlzLnNhbXBsZVJhdGVcbiAgICB9O1xuICB9XG5cbiAgcHVibGljIHRvZ2dsZUZpbHRlcihmaWx0ZXI6IENvbW1vblJlc2FtcGxlckZpbHRlclByZXNldCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHNhbWUgPSB0aGlzLmN1cnJlbnRGaWx0ZXIgPT09IGZpbHRlcjtcbiAgICB0aGlzLnNldEZpbHRlcihzYW1lID8gbnVsbCA6IGZpbHRlcik7XG5cbiAgICByZXR1cm4gIXNhbWU7XG4gIH1cblxuICBwdWJsaWMgZ2V0UmF0aW8oKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5pbnB1dFNhbXBsZVJhdGUgPT09IDApIHJldHVybiAxO1xuXG4gICAgcmV0dXJuIHRoaXMuc2FtcGxlUmF0ZSAvIHRoaXMuaW5wdXRTYW1wbGVSYXRlO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNhbXBsZShpbnB1dDogQnVmZmVyKTogQnVmZmVyIHtcbiAgICBjb25zdCBieXRlc1BlckZyYW1lID0gdGhpcy5ieXRlcyAqIHRoaXMuY2hhbm5lbHM7XG4gICAgY29uc3QgaW5wdXRGcmFtZXMgPSBNYXRoLmZsb29yKGlucHV0Lmxlbmd0aCAvIGJ5dGVzUGVyRnJhbWUpO1xuICAgIGNvbnN0IG91dHB1dEZyYW1lcyA9IE1hdGguZmxvb3IoXG4gICAgICBpbnB1dEZyYW1lcyAqIHRoaXMuaW5wdXRTYW1wbGVSYXRlIC8gdGhpcy5zYW1wbGVSYXRlXG4gICAgKTtcbiAgICBjb25zdCBvdXRwdXQgPSBCdWZmZXIuYWxsb2Mob3V0cHV0RnJhbWVzICogYnl0ZXNQZXJGcmFtZSk7XG5cbiAgICBmb3IgKGxldCBvdXRGcmFtZSA9IDA7IG91dEZyYW1lIDwgb3V0cHV0RnJhbWVzOyBvdXRGcmFtZSsrKSB7XG4gICAgICBjb25zdCBpblBvcyA9IG91dEZyYW1lICogdGhpcy5zYW1wbGVSYXRlIC8gdGhpcy5pbnB1dFNhbXBsZVJhdGU7XG4gICAgICBjb25zdCBpbkZyYW1lID0gTWF0aC5mbG9vcihpblBvcyk7XG5cbiAgICAgIGlmIChcbiAgICAgIGluRnJhbWUgPj0gaW5wdXRGcmFtZXMgLSAxIHx8XG4gICAgICAoaW5GcmFtZSArIDEpICogYnl0ZXNQZXJGcmFtZSArICh0aGlzLmNoYW5uZWxzIC0gMSkgKiB0aGlzLmJ5dGVzID5cbiAgICAgIGlucHV0Lmxlbmd0aClcbiAgICAgIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGZyYWN0aW9uID0gaW5Qb3MgLSBpbkZyYW1lO1xuXG4gICAgICBmb3IgKGxldCBjaGFubmVsID0gMDsgY2hhbm5lbCA8IHRoaXMuY2hhbm5lbHM7IGNoYW5uZWwrKykge1xuICAgICAgICBjb25zdCBwb3MxID0gaW5GcmFtZSAqIGJ5dGVzUGVyRnJhbWUgKyBjaGFubmVsICogdGhpcy5ieXRlcztcbiAgICAgICAgY29uc3QgcG9zMiA9IChpbkZyYW1lICsgMSkgKiBieXRlc1BlckZyYW1lICsgY2hhbm5lbCAqIHRoaXMuYnl0ZXM7XG5cbiAgICAgICAgaWYgKFxuICAgICAgICBwb3MxICsgdGhpcy5ieXRlcyA+IGlucHV0Lmxlbmd0aCB8fFxuICAgICAgICBwb3MyICsgdGhpcy5ieXRlcyA+IGlucHV0Lmxlbmd0aClcbiAgICAgICAge1xuICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc2FtcGxlMSA9IHRoaXMuX3JlYWRJbnQoaW5wdXQsIHBvczEpO1xuICAgICAgICBjb25zdCBzYW1wbGUyID0gdGhpcy5fcmVhZEludChpbnB1dCwgcG9zMik7XG5cbiAgICAgICAgY29uc3QgaW50ZXJwb2xhdGVkID0gc2FtcGxlMSArIGZyYWN0aW9uICogKHNhbXBsZTIgLSBzYW1wbGUxKTtcbiAgICAgICAgY29uc3QgY2xhbXBlZCA9IHRoaXMuY2xhbXAoTWF0aC5yb3VuZChpbnRlcnBvbGF0ZWQpKTtcblxuICAgICAgICBjb25zdCBvdXRQb3MgPSBvdXRGcmFtZSAqIGJ5dGVzUGVyRnJhbWUgKyBjaGFubmVsICogdGhpcy5ieXRlcztcbiAgICAgICAgdGhpcy5fd3JpdGVJbnQob3V0cHV0LCBjbGFtcGVkLCBvdXRQb3MpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvdXRwdXQ7XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgX3RyYW5zZm9ybShcbiAgY2h1bms6IEJ1ZmZlcixcbiAgZW5jb2Rpbmc6IEJ1ZmZlckVuY29kaW5nLFxuICBjYWxsYmFjazogKGVycm9yPzogRXJyb3IgfCBudWxsLCBkYXRhPzogQnVmZmVyKSA9PiB2b2lkKVxuICA6IHZvaWQge1xuICAgIGlmICh0aGlzLmRpc2FibGVkIHx8IHRoaXMuc2FtcGxlUmF0ZSA9PT0gdGhpcy5pbnB1dFNhbXBsZVJhdGUpIHtcbiAgICAgIHRoaXMucHVzaChjaHVuayk7XG4gICAgICBjYWxsYmFjaygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuYnVmZmVyID0gQnVmZmVyLmNvbmNhdChbdGhpcy5idWZmZXIsIGNodW5rXSk7XG5cbiAgICBjb25zdCBieXRlc1BlckZyYW1lID0gdGhpcy5ieXRlcyAqIHRoaXMuY2hhbm5lbHM7XG4gICAgY29uc3QgbWluRnJhbWVzTmVlZGVkID0gTWF0aC5jZWlsKFxuICAgICAgYnl0ZXNQZXJGcmFtZSAqICh0aGlzLmlucHV0U2FtcGxlUmF0ZSAvIHRoaXMuc2FtcGxlUmF0ZSlcbiAgICApO1xuICAgIGNvbnN0IGNvbXBsZXRlRnJhbWVzID0gTWF0aC5mbG9vcih0aGlzLmJ1ZmZlci5sZW5ndGggLyBieXRlc1BlckZyYW1lKSAtIDE7XG5cbiAgICBpZiAoY29tcGxldGVGcmFtZXMgPj0gbWluRnJhbWVzTmVlZGVkKSB7XG4gICAgICBjb25zdCBwcm9jZXNzU2l6ZSA9IGNvbXBsZXRlRnJhbWVzICogYnl0ZXNQZXJGcmFtZTtcbiAgICAgIGNvbnN0IHRvUHJvY2VzcyA9IHRoaXMuYnVmZmVyLnNsaWNlKDAsIHByb2Nlc3NTaXplKTtcbiAgICAgIHRoaXMuYnVmZmVyID0gdGhpcy5idWZmZXIuc2xpY2UocHJvY2Vzc1NpemUpO1xuXG4gICAgICBjb25zdCByZXNhbXBsZWQgPSB0aGlzLnJlc2FtcGxlKHRvUHJvY2Vzcyk7XG4gICAgICB0aGlzLnB1c2gocmVzYW1wbGVkKTtcbiAgICB9XG5cbiAgICBjYWxsYmFjaygpO1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIF9mbHVzaChcbiAgY2FsbGJhY2s6IChlcnJvcj86IEVycm9yIHwgbnVsbCwgZGF0YT86IEJ1ZmZlcikgPT4gdm9pZClcbiAgOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkge1xuICAgICAgY2FsbGJhY2soKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5idWZmZXIubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgcmVzYW1wbGVkID0gdGhpcy5yZXNhbXBsZSh0aGlzLmJ1ZmZlcik7XG4gICAgICB0aGlzLnB1c2gocmVzYW1wbGVkKTtcbiAgICB9XG4gICAgY2FsbGJhY2soKTtcbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZSBzZXRTYW1wbGVSYXRlKHJhdGU6IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChyYXRlID09PSB0aGlzLnNhbXBsZVJhdGUpIHJldHVybjtcblxuICAgIGlmIChyYXRlIDwgMSkge1xuICAgICAgdGhyb3cgbmV3IFJhbmdlRXJyb3IoJ1NhbXBsZSByYXRlIG11c3QgYmUgZ3JlYXRlciB0aGFuIDAnKTtcbiAgICB9XG5cbiAgICBzdXBlci5zZXRTYW1wbGVSYXRlKHJhdGUpO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxufSIsICJpbXBvcnQgeyBUcmFuc2Zvcm1DYWxsYmFjayB9IGZyb20gJ3N0cmVhbSc7XG5pbXBvcnQgeyBQQ01UcmFuc2Zvcm1lciwgUENNVHJhbnNmb3JtZXJPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFZvbHVtZVRyYW5zZm9ybWVyT3B0aW9ucyBleHRlbmRzIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB7XG4gIHZvbHVtZT86IG51bWJlcjtcbn1cblxuZXhwb3J0IGNsYXNzIFZvbHVtZVRyYW5zZm9ybWVyIGV4dGVuZHMgUENNVHJhbnNmb3JtZXIge1xuICBwcml2YXRlIF92b2x1bWUgPSAxO1xuICBwdWJsaWMgY29uc3RydWN0b3Iob3B0aW9ucz86IFZvbHVtZVRyYW5zZm9ybWVyT3B0aW9ucykge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zPy52b2x1bWUgPT09ICdudW1iZXInKSB7XG4gICAgICB0aGlzLnNldFZvbHVtZShvcHRpb25zLnZvbHVtZSk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdldCB2b2x1bWVBcHByb3goKSB7XG4gICAgcmV0dXJuIHRoaXMuX3ZvbHVtZSAqIDEwMDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdm9sdW1lKCkge1xuICAgIHJldHVybiBNYXRoLmZsb29yKHRoaXMudm9sdW1lQXBwcm94KTtcbiAgfVxuXG4gIHB1YmxpYyBzZXQgdm9sdW1lKHZvbHVtZTogbnVtYmVyKSB7XG4gICAgdGhpcy5zZXRWb2x1bWUodm9sdW1lKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRWb2x1bWUodm9sdW1lOiBudW1iZXIpIHtcbiAgICBpZiAodHlwZW9mIHZvbHVtZSAhPT0gJ251bWJlcicgfHwgaXNOYU4odm9sdW1lKSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgRXhwZWN0ZWQgdm9sdW1lIGFtb3VudCB0byBiZSBhIG51bWJlciwgcmVjZWl2ZWQgJHt0eXBlb2Ygdm9sdW1lfSFgXG4gICAgKTtcbiAgICBpZiAodm9sdW1lIDwgMCkgdm9sdW1lID0gMDtcbiAgICBpZiAoIWlzRmluaXRlKHZvbHVtZSkpIHZvbHVtZSA9IDEwMDtcblxuICAgIHRoaXMuX3ZvbHVtZSA9IHZvbHVtZSAvIDEwMDtcblxuICAgIHRoaXMub25VcGRhdGU/LigpO1xuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBwdWJsaWMgX3RyYW5zZm9ybShcbiAgY2h1bms6IEJ1ZmZlcixcbiAgZW5jb2Rpbmc6IEJ1ZmZlckVuY29kaW5nLFxuICBjYWxsYmFjazogVHJhbnNmb3JtQ2FsbGJhY2spXG4gIDogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQgfHwgdGhpcy5fdm9sdW1lID09PSAxKSB7XG4gICAgICB0aGlzLnB1c2goY2h1bmspO1xuICAgICAgcmV0dXJuIGNhbGxiYWNrKCk7XG4gICAgfVxuXG4gICAgY29uc3QgbGVuID0gTWF0aC5mbG9vcihjaHVuay5sZW5ndGggLyAyKSAqIDI7XG4gICAgY29uc3QgeyBieXRlcyB9ID0gdGhpcztcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuOyBpICs9IGJ5dGVzKSB7XG4gICAgICBjb25zdCBpbnQgPSB0aGlzLl9yZWFkSW50KGNodW5rLCBpKTtcbiAgICAgIGNvbnN0IGFtcCA9IHRoaXMuY2xhbXAoaW50ICogdGhpcy5fdm9sdW1lKTtcbiAgICAgIHRoaXMuX3dyaXRlSW50KGNodW5rLCBhbXAsIGkpO1xuICAgIH1cblxuICAgIHRoaXMucHVzaChjaHVuayk7XG5cbiAgICByZXR1cm4gY2FsbGJhY2soKTtcbiAgfVxuXG4gIHB1YmxpYyB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gYCR7dGhpcy52b2x1bWV9JWA7XG4gIH1cbn0iLCAiaW1wb3J0IHsgUENNVHJhbnNmb3JtZXIsIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzL1BDTVRyYW5zZm9ybWVyJztcblxuZXhwb3J0IGludGVyZmFjZSBDb21wcmVzc29yT3B0aW9ucyBleHRlbmRzIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB7XG4gIHRocmVzaG9sZD86IG51bWJlcjtcbiAgcmF0aW8/OiBudW1iZXI7XG4gIGF0dGFjaz86IG51bWJlcjtcbiAgcmVsZWFzZT86IG51bWJlcjtcbiAgbWFrZXVwR2Fpbj86IG51bWJlcjtcbiAga25lZVdpZHRoPzogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbXByZXNzb3JQYXJhbWV0ZXJzIHtcbiAgdGhyZXNob2xkOiBudW1iZXI7XG4gIHJhdGlvOiBudW1iZXI7XG4gIGF0dGFjazogbnVtYmVyO1xuICByZWxlYXNlOiBudW1iZXI7XG4gIG1ha2V1cEdhaW46IG51bWJlcjtcbiAga25lZVdpZHRoOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBDb21wcmVzc29yVHJhbnNmb3JtZXIgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lciB7XG4gIHByaXZhdGUgdGhyZXNob2xkOiBudW1iZXI7XG4gIHByaXZhdGUgcmF0aW86IG51bWJlcjtcbiAgcHJpdmF0ZSBhdHRhY2s6IG51bWJlcjtcbiAgcHJpdmF0ZSByZWxlYXNlOiBudW1iZXI7XG4gIHByaXZhdGUgbWFrZXVwR2FpbjogbnVtYmVyO1xuICBwcml2YXRlIGtuZWVXaWR0aDogbnVtYmVyO1xuICBwcml2YXRlIGVudmVsb3BlOiBudW1iZXIgPSAwO1xuICBwcml2YXRlIGdhaW5SZWR1Y3Rpb246IG51bWJlciA9IDE7XG4gIHByaXZhdGUgcHJldmlvdXNHYWluUmVkdWN0aW9uOiBudW1iZXIgPSAxO1xuXG4gIGNvbnN0cnVjdG9yKG9wdGlvbnM6IENvbXByZXNzb3JPcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIHRoaXMudGhyZXNob2xkID0gb3B0aW9ucy50aHJlc2hvbGQgPz8gLTIwO1xuICAgIHRoaXMucmF0aW8gPSBvcHRpb25zLnJhdGlvID8/IDQ7XG4gICAgdGhpcy5hdHRhY2sgPSBvcHRpb25zLmF0dGFjayA/PyAyMDtcbiAgICB0aGlzLnJlbGVhc2UgPSBvcHRpb25zLnJlbGVhc2UgPz8gMTAwO1xuICAgIHRoaXMubWFrZXVwR2FpbiA9IG9wdGlvbnMubWFrZXVwR2FpbiA/PyAwO1xuICAgIHRoaXMua25lZVdpZHRoID0gb3B0aW9ucy5rbmVlV2lkdGggPz8gNjtcbiAgICB0aGlzLmF0dGFjayA9IE1hdGguZXhwKC0xIC8gKHRoaXMuc2FtcGxlUmF0ZSAqIHRoaXMuYXR0YWNrIC8gMTAwMCkpO1xuICAgIHRoaXMucmVsZWFzZSA9IE1hdGguZXhwKC0xIC8gKHRoaXMuc2FtcGxlUmF0ZSAqIHRoaXMucmVsZWFzZSAvIDEwMDApKTtcbiAgfVxuXG4gIHByaXZhdGUgbGluZWFyVG9EYihsaW5lYXI6IG51bWJlcik6IG51bWJlciB7XG4gICAgY29uc3QgdmFsID0gMjAgKiBNYXRoLmxvZzEwKE1hdGgubWF4KGxpbmVhciwgMWUtNikpO1xuICAgIHJldHVybiB2YWw7XG4gIH1cblxuICBwcml2YXRlIGRiVG9MaW5lYXIoZGI6IG51bWJlcik6IG51bWJlciB7XG4gICAgY29uc3QgdmFsID0gTWF0aC5wb3coMTAsIGRiIC8gMjApO1xuICAgIHJldHVybiB2YWw7XG4gIH1cblxuICBwdWJsaWMgc2V0VGhyZXNob2xkKGRiOiBudW1iZXIpIHtcbiAgICB0aGlzLnRocmVzaG9sZCA9IE1hdGgubWF4KC0xMDAsIE1hdGgubWluKDAsIGRiKSk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIHNldFJhdGlvKHJhdGlvOiBudW1iZXIpIHtcbiAgICB0aGlzLnJhdGlvID0gTWF0aC5tYXgoMSwgcmF0aW8pO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRBdHRhY2sobXM6IG51bWJlcikge1xuICAgIHRoaXMuYXR0YWNrID0gTWF0aC5leHAoLTEgLyAodGhpcy5zYW1wbGVSYXRlICogTWF0aC5tYXgoMC4xLCBtcykgLyAxMDAwKSk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIHNldFJlbGVhc2UobXM6IG51bWJlcikge1xuICAgIHRoaXMucmVsZWFzZSA9IE1hdGguZXhwKFxuICAgICAgLTEgLyAodGhpcy5zYW1wbGVSYXRlICogTWF0aC5tYXgoMC4xLCBtcykgLyAxMDAwKVxuICAgICk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIHNldE1ha2V1cEdhaW4oZGI6IG51bWJlcikge1xuICAgIHRoaXMubWFrZXVwR2FpbiA9IE1hdGgubWF4KC0yMCwgTWF0aC5taW4oMjAsIGRiKSk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIHNldEtuZWVXaWR0aChkYjogbnVtYmVyKSB7XG4gICAgdGhpcy5rbmVlV2lkdGggPSBNYXRoLm1heCgwLCBNYXRoLm1pbigyMCwgZGIpKTtcbiAgICB0aGlzLm9uVXBkYXRlKCk7XG4gIH1cblxuICBwdWJsaWMgc2V0Q29tcHJlc3NvcihvcHRpb25zOiBQYXJ0aWFsPENvbXByZXNzb3JQYXJhbWV0ZXJzPikge1xuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy50aHJlc2hvbGQgPT09ICdudW1iZXInKSB7XG4gICAgICB0aGlzLnNldFRocmVzaG9sZChvcHRpb25zLnRocmVzaG9sZCk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLnJhdGlvID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXRSYXRpbyhvcHRpb25zLnJhdGlvKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMuYXR0YWNrID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXRBdHRhY2sob3B0aW9ucy5hdHRhY2spO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy5yZWxlYXNlID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXRSZWxlYXNlKG9wdGlvbnMucmVsZWFzZSk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLm1ha2V1cEdhaW4gPT09ICdudW1iZXInKSB7XG4gICAgICB0aGlzLnNldE1ha2V1cEdhaW4ob3B0aW9ucy5tYWtldXBHYWluKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMua25lZVdpZHRoID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXRLbmVlV2lkdGgob3B0aW9ucy5rbmVlV2lkdGgpO1xuICAgIH1cblxuICAgIHRoaXMub25VcGRhdGUoKTtcblxuICAgIHJldHVybiB0aGlzLmdldFBhcmFtZXRlcnMoKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRQYXJhbWV0ZXJzKCk6IENvbXByZXNzb3JQYXJhbWV0ZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgdGhyZXNob2xkOiB0aGlzLnRocmVzaG9sZCxcbiAgICAgIHJhdGlvOiB0aGlzLnJhdGlvLFxuICAgICAgYXR0YWNrOiB0aGlzLmF0dGFjayxcbiAgICAgIHJlbGVhc2U6IHRoaXMucmVsZWFzZSxcbiAgICAgIG1ha2V1cEdhaW46IHRoaXMubWFrZXVwR2FpbixcbiAgICAgIGtuZWVXaWR0aDogdGhpcy5rbmVlV2lkdGhcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBjb21wdXRlR2FpblJlZHVjdGlvbihpbnB1dExldmVsOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IGlucHV0RGIgPSB0aGlzLmxpbmVhclRvRGIoaW5wdXRMZXZlbCk7XG5cbiAgICBsZXQgZ2FpblJlZHVjdGlvbkRiID0gMDtcblxuICAgIGlmICgyICogKGlucHV0RGIgLSB0aGlzLnRocmVzaG9sZCkgPCAtdGhpcy5rbmVlV2lkdGgpIHtcbiAgICAgIGdhaW5SZWR1Y3Rpb25EYiA9IDA7XG4gICAgfSBlbHNlIGlmICgyICogTWF0aC5hYnMoaW5wdXREYiAtIHRoaXMudGhyZXNob2xkKSA8PSB0aGlzLmtuZWVXaWR0aCkge1xuICAgICAgY29uc3QgeCA9IGlucHV0RGIgLSB0aGlzLnRocmVzaG9sZCArIHRoaXMua25lZVdpZHRoIC8gMjtcbiAgICAgIGdhaW5SZWR1Y3Rpb25EYiA9XG4gICAgICAoMSAvIHRoaXMucmF0aW8gLSAxKSAqIE1hdGgucG93KHgsIDIpIC8gKDIgKiB0aGlzLmtuZWVXaWR0aCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGdhaW5SZWR1Y3Rpb25EYiA9IChpbnB1dERiIC0gdGhpcy50aHJlc2hvbGQpICogKDEgLSAxIC8gdGhpcy5yYXRpbyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZGJUb0xpbmVhcigtZ2FpblJlZHVjdGlvbkRiICsgdGhpcy5tYWtldXBHYWluKTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvY2Vzc1NhbXBsZShpbnB1dDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkgcmV0dXJuIGlucHV0O1xuXG4gICAgY29uc3QgaW5wdXRGbG9hdCA9IGlucHV0IC8gdGhpcy5leHRyZW11bTtcblxuICAgIGNvbnN0IGlucHV0TGV2ZWwgPSBNYXRoLmFicyhpbnB1dEZsb2F0KTtcbiAgICBjb25zdCBjb2VmZiA9IGlucHV0TGV2ZWwgPiB0aGlzLmVudmVsb3BlID8gdGhpcy5hdHRhY2sgOiB0aGlzLnJlbGVhc2U7XG4gICAgdGhpcy5lbnZlbG9wZSA9IGNvZWZmICogdGhpcy5lbnZlbG9wZSArICgxIC0gY29lZmYpICogaW5wdXRMZXZlbDtcblxuICAgIGNvbnN0IHRhcmdldEdhaW5SZWR1Y3Rpb24gPSB0aGlzLmNvbXB1dGVHYWluUmVkdWN0aW9uKHRoaXMuZW52ZWxvcGUpO1xuXG4gICAgdGhpcy5nYWluUmVkdWN0aW9uID0gTWF0aC5taW4oXG4gICAgICB0aGlzLnByZXZpb3VzR2FpblJlZHVjdGlvbiAqIHRoaXMuYXR0YWNrICtcbiAgICAgIHRhcmdldEdhaW5SZWR1Y3Rpb24gKiAoMSAtIHRoaXMuYXR0YWNrKSxcbiAgICAgIHRhcmdldEdhaW5SZWR1Y3Rpb25cbiAgICApO1xuICAgIHRoaXMucHJldmlvdXNHYWluUmVkdWN0aW9uID0gdGhpcy5nYWluUmVkdWN0aW9uO1xuXG4gICAgY29uc3Qgb3V0cHV0RmxvYXQgPSBpbnB1dEZsb2F0ICogdGhpcy5nYWluUmVkdWN0aW9uO1xuXG4gICAgcmV0dXJuIHRoaXMuY2xhbXAoTWF0aC5mbG9vcihvdXRwdXRGbG9hdCAqIHRoaXMuZXh0cmVtdW0pKTtcbiAgfVxuXG4gIHB1YmxpYyBvdmVycmlkZSBfdHJhbnNmb3JtKFxuICBjaHVuazogQnVmZmVyLFxuICBlbmNvZGluZzogQnVmZmVyRW5jb2RpbmcsXG4gIGNhbGxiYWNrOiAoZXJyb3I/OiBFcnJvciB8IG51bGwsIGRhdGE/OiBCdWZmZXIpID0+IHZvaWQpXG4gIDogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHtcbiAgICAgIGNhbGxiYWNrKG51bGwsIGNodW5rKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXQgPSBCdWZmZXIuYWxsb2MoY2h1bmsubGVuZ3RoKTtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2h1bmsubGVuZ3RoOyBpICs9IHRoaXMuYnl0ZXMpIHtcbiAgICAgIGNvbnN0IHNhbXBsZSA9IHRoaXMuX3JlYWRJbnQoY2h1bmssIGkpO1xuICAgICAgY29uc3QgcHJvY2Vzc2VkID0gdGhpcy5wcm9jZXNzU2FtcGxlKHNhbXBsZSk7XG4gICAgICB0aGlzLl93cml0ZUludChvdXRwdXQsIHByb2Nlc3NlZCwgaSk7XG4gICAgfVxuXG4gICAgY2FsbGJhY2sobnVsbCwgb3V0cHV0KTtcbiAgfVxufSIsICJpbXBvcnQgeyBQQ01UcmFuc2Zvcm1lciwgUENNVHJhbnNmb3JtZXJPcHRpb25zIH0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IHsgRXZlbnRFbWl0dGVyIH0gZnJvbSAnZXZlbnRzJztcblxuZXhwb3J0IGludGVyZmFjZSBQQ01TZWVrZXJPcHRpb25zIGV4dGVuZHMgUENNVHJhbnNmb3JtZXJPcHRpb25zIHtcbiAgdG90YWxEdXJhdGlvbjogbnVtYmVyO1xuICBjaGFubmVsczogbnVtYmVyO1xuICBzZWVrVGFyZ2V0PzogbnVtYmVyIHwgbnVsbDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZWVrZXJQYXJhbWV0ZXJzIHtcbiAgY3VycmVudFBvc2l0aW9uOiBudW1iZXI7XG4gIHNlZWtUYXJnZXQ6IG51bWJlciB8IG51bGw7XG4gIHRvdGFsRHVyYXRpb246IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZWVrRXZlbnQge1xuICBwb3NpdGlvbjogbnVtYmVyO1xuICBzYW1wbGU6IG51bWJlcjtcbiAgYnl0ZVBvc2l0aW9uOiBudW1iZXI7XG59XG5cbmV4cG9ydCBjbGFzcyBQQ01TZWVrZXJUcmFuc2Zvcm1lciBleHRlbmRzIFBDTVRyYW5zZm9ybWVyIHtcbiAgcHJpdmF0ZSB0b3RhbER1cmF0aW9uOiBudW1iZXI7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2hhbm5lbHM6IG51bWJlcjtcbiAgcHJpdmF0ZSBieXRlc1BlckZyYW1lITogbnVtYmVyO1xuICBwcml2YXRlIGN1cnJlbnRQb3NpdGlvbiA9IDA7XG4gIHByaXZhdGUgc2Vla1RhcmdldDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgYnVmZmVyOiBCdWZmZXIgPSBCdWZmZXIuYWxsb2MoMCk7XG4gIHB1YmxpYyByZWFkb25seSBldmVudHMgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKFxuICBvcHRpb25zOiBQQ01TZWVrZXJPcHRpb25zID0ge1xuICAgIGNoYW5uZWxzOiAyLFxuICAgIHRvdGFsRHVyYXRpb246IDBcbiAgfSlcbiAge1xuICAgIHN1cGVyKG9wdGlvbnMpO1xuXG4gICAgaWYgKG9wdGlvbnMudG90YWxEdXJhdGlvbiA9PSBudWxsIHx8IG9wdGlvbnMudG90YWxEdXJhdGlvbiA8IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndG90YWxEdXJhdGlvbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gICAgfVxuXG4gICAgaWYgKCFvcHRpb25zLmNoYW5uZWxzIHx8IG9wdGlvbnMuY2hhbm5lbHMgPD0gMCkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdjaGFubmVscyBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gICAgfVxuXG4gICAgdGhpcy50b3RhbER1cmF0aW9uID0gb3B0aW9ucy50b3RhbER1cmF0aW9uO1xuICAgIHRoaXMuY2hhbm5lbHMgPSBvcHRpb25zLmNoYW5uZWxzO1xuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLnNlZWtUYXJnZXQgPT09ICdudW1iZXInICYmIG9wdGlvbnMuc2Vla1RhcmdldCA+IDApIHtcbiAgICAgIHRoaXMuc2Vla1RhcmdldCA9IG9wdGlvbnMuc2Vla1RhcmdldDtcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZURlcGVuZGVudFZhbHVlcygpO1xuICB9XG5cbiAgcHVibGljIGdldFBhcmFtZXRlcnMoKTogU2Vla2VyUGFyYW1ldGVycyB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGN1cnJlbnRQb3NpdGlvbjogdGhpcy5jdXJyZW50UG9zaXRpb24sXG4gICAgICBzZWVrVGFyZ2V0OiB0aGlzLnNlZWtUYXJnZXQsXG4gICAgICB0b3RhbER1cmF0aW9uOiB0aGlzLnRvdGFsRHVyYXRpb25cbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVEZXBlbmRlbnRWYWx1ZXMoKTogdm9pZCB7XG4gICAgdGhpcy5ieXRlc1BlckZyYW1lID0gdGhpcy5ieXRlcyAqIHRoaXMuY2hhbm5lbHM7XG5cbiAgICBpZiAodGhpcy5jdXJyZW50UG9zaXRpb24gPiAwKSB7XG4gICAgICBjb25zdCBjdXJyZW50TXMgPSB0aGlzLmN1cnJlbnRQb3NpdGlvbiAvICh0aGlzLnNhbXBsZVJhdGUgLyAxMDAwKTtcbiAgICAgIHRoaXMuY3VycmVudFBvc2l0aW9uID0gTWF0aC5mbG9vcihjdXJyZW50TXMgLyAxMDAwICogdGhpcy5zYW1wbGVSYXRlKTtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zZWVrVGFyZ2V0ICE9PSBudWxsKSB7XG4gICAgICBjb25zdCBzZWVrTXMgPSB0aGlzLnNlZWtUYXJnZXQgLyAodGhpcy5zYW1wbGVSYXRlIC8gMTAwMCk7XG4gICAgICB0aGlzLnNlZWtUYXJnZXQgPSBNYXRoLmZsb29yKHNlZWtNcyAvIDEwMDAgKiB0aGlzLnNhbXBsZVJhdGUpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGUgYnl0ZSBwb3NpdGlvbiBmcm9tIHNhbXBsZSBwb3NpdGlvblxuICAgKiBAcGFyYW0gc2FtcGxlUG9zaXRpb24gUG9zaXRpb24gaW4gc2FtcGxlc1xuICAgKiBAcmV0dXJucyBQb3NpdGlvbiBpbiBieXRlc1xuICAgKi9cbiAgcHJpdmF0ZSBzYW1wbGVUb0J5dGVQb3NpdGlvbihzYW1wbGVQb3NpdGlvbjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gc2FtcGxlUG9zaXRpb24gKiB0aGlzLmJ5dGVzUGVyRnJhbWU7XG4gIH1cblxuICBwdWJsaWMgc2V0VG90YWxEdXJhdGlvbihkdXJhdGlvbjogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKGR1cmF0aW9uIDw9IDApIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcigndG90YWxEdXJhdGlvbiBtdXN0IGJlIGEgcG9zaXRpdmUgbnVtYmVyJyk7XG4gICAgfVxuXG4gICAgdGhpcy50b3RhbER1cmF0aW9uID0gZHVyYXRpb247XG4gICAgdGhpcy51cGRhdGVEZXBlbmRlbnRWYWx1ZXMoKTtcbiAgICB0aGlzLm9uVXBkYXRlKCk7XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgc2V0U2FtcGxlUmF0ZShyYXRlOiBudW1iZXIpOiB2b2lkIHtcbiAgICBzdXBlci5zZXRTYW1wbGVSYXRlKHJhdGUpO1xuICAgIHRoaXMudXBkYXRlRGVwZW5kZW50VmFsdWVzKCk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFNlZWsgdG8gYSBzcGVjaWZpYyBwb3NpdGlvbiBpbiBtaWxsaXNlY29uZHNcbiAgICogQHBhcmFtIG1zIFBvc2l0aW9uIGluIG1pbGxpc2Vjb25kcyAobmVnYXRpdmUgdmFsdWVzIHNlZWsgZnJvbSBlbmQpXG4gICAqIEByZXR1cm5zIEFjdHVhbCBwb3NpdGlvbiBpbiBtaWxsaXNlY29uZHMgYWZ0ZXIgc2Vla2luZ1xuICAgKi9cbiAgcHVibGljIHNlZWsobXM6IG51bWJlcik6IG51bWJlciB7XG4gICAgaWYgKHRoaXMudG90YWxEdXJhdGlvbiA9PT0gMCkgcmV0dXJuIDA7XG5cbiAgICBpZiAobXMgPCAwKSB7XG4gICAgICBtcyA9IE1hdGgubWF4KDAsIHRoaXMudG90YWxEdXJhdGlvbiArIG1zKTtcbiAgICB9XG5cbiAgICBtcyA9IE1hdGgubWF4KDAsIE1hdGgubWluKHRoaXMudG90YWxEdXJhdGlvbiwgbXMpKTtcbiAgICBjb25zdCB0YXJnZXRTYW1wbGUgPSBNYXRoLmZsb29yKG1zIC8gMTAwMCAqIHRoaXMuc2FtcGxlUmF0ZSk7XG5cbiAgICBpZiAodGFyZ2V0U2FtcGxlIDwgdGhpcy5jdXJyZW50UG9zaXRpb24pIHtcbiAgICAgIHRoaXMuYnVmZmVyID0gQnVmZmVyLmFsbG9jKDApO1xuXG4gICAgICBjb25zdCBieXRlUG9zaXRpb24gPSB0aGlzLnNhbXBsZVRvQnl0ZVBvc2l0aW9uKHRhcmdldFNhbXBsZSk7XG5cbiAgICAgIHRoaXMuZXZlbnRzLmVtaXQoJ3NlZWsnLCB7XG4gICAgICAgIHBvc2l0aW9uOiBtcyxcbiAgICAgICAgc2FtcGxlOiB0YXJnZXRTYW1wbGUsXG4gICAgICAgIGJ5dGVQb3NpdGlvbjogYnl0ZVBvc2l0aW9uXG4gICAgICB9IGFzIFNlZWtFdmVudCk7XG4gICAgfVxuXG4gICAgdGhpcy5zZWVrVGFyZ2V0ID0gdGFyZ2V0U2FtcGxlO1xuICAgIHJldHVybiB0YXJnZXRTYW1wbGUgLyB0aGlzLnNhbXBsZVJhdGUgKiAxMDAwO1xuICB9XG5cbiAgcHVibGljIGdldFBvc2l0aW9uKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuY3VycmVudFBvc2l0aW9uIC8gdGhpcy5zYW1wbGVSYXRlICogMTAwMDtcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlU2VlayhjaHVuazogQnVmZmVyKTogQnVmZmVyIHtcbiAgICBpZiAodGhpcy5zZWVrVGFyZ2V0ID09PSBudWxsKSByZXR1cm4gY2h1bms7XG5cbiAgICBjb25zdCBjaHVua1N0YXJ0U2FtcGxlID0gdGhpcy5jdXJyZW50UG9zaXRpb247XG4gICAgY29uc3QgY2h1bmtTYW1wbGVzID0gTWF0aC5mbG9vcihjaHVuay5sZW5ndGggLyB0aGlzLmJ5dGVzUGVyRnJhbWUpO1xuICAgIGNvbnN0IGNodW5rRW5kU2FtcGxlID0gY2h1bmtTdGFydFNhbXBsZSArIGNodW5rU2FtcGxlcztcblxuICAgIGlmICh0aGlzLnNlZWtUYXJnZXQgPj0gY2h1bmtFbmRTYW1wbGUpIHtcbiAgICAgIHRoaXMuY3VycmVudFBvc2l0aW9uICs9IGNodW5rU2FtcGxlcztcbiAgICAgIHJldHVybiBCdWZmZXIuYWxsb2MoMCk7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2Vla1RhcmdldCA+PSBjaHVua1N0YXJ0U2FtcGxlKSB7XG4gICAgICBjb25zdCBvZmZzZXRTYW1wbGVzID0gdGhpcy5zZWVrVGFyZ2V0IC0gY2h1bmtTdGFydFNhbXBsZTtcbiAgICAgIGNvbnN0IG9mZnNldEJ5dGVzID0gb2Zmc2V0U2FtcGxlcyAqIHRoaXMuYnl0ZXNQZXJGcmFtZTtcbiAgICAgIHRoaXMuY3VycmVudFBvc2l0aW9uID0gdGhpcy5zZWVrVGFyZ2V0O1xuICAgICAgdGhpcy5zZWVrVGFyZ2V0ID0gbnVsbDtcbiAgICAgIHJldHVybiBjaHVuay5zdWJhcnJheShvZmZzZXRCeXRlcyk7XG4gICAgfVxuXG4gICAgdGhpcy5jdXJyZW50UG9zaXRpb24gPSB0aGlzLnNlZWtUYXJnZXQ7XG4gICAgdGhpcy5zZWVrVGFyZ2V0ID0gbnVsbDtcbiAgICByZXR1cm4gY2h1bms7XG4gIH1cblxuICBwdWJsaWMgb3ZlcnJpZGUgX3RyYW5zZm9ybShcbiAgY2h1bms6IEJ1ZmZlcixcbiAgZW5jb2Rpbmc6IEJ1ZmZlckVuY29kaW5nLFxuICBjYWxsYmFjazogKGVycm9yPzogRXJyb3IgfCBudWxsLCBkYXRhPzogQnVmZmVyKSA9PiB2b2lkKVxuICA6IHZvaWQge1xuICAgIHRyeSB7XG4gICAgICBpZiAodGhpcy5kaXNhYmxlZCB8fCB0aGlzLnRvdGFsRHVyYXRpb24gPT09IDApIHtcbiAgICAgICAgY2FsbGJhY2sobnVsbCwgY2h1bmspO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNvbWJpbmVkQnVmZmVyID0gQnVmZmVyLmNvbmNhdChbdGhpcy5idWZmZXIsIGNodW5rXSk7XG4gICAgICBjb25zdCBmcmFtZUNvdW50ID0gTWF0aC5mbG9vcihjb21iaW5lZEJ1ZmZlci5sZW5ndGggLyB0aGlzLmJ5dGVzUGVyRnJhbWUpO1xuICAgICAgY29uc3QgcHJvY2Vzc2FibGVCeXRlcyA9IGZyYW1lQ291bnQgKiB0aGlzLmJ5dGVzUGVyRnJhbWU7XG5cbiAgICAgIHRoaXMuYnVmZmVyID0gY29tYmluZWRCdWZmZXIuc3ViYXJyYXkocHJvY2Vzc2FibGVCeXRlcyk7XG5cbiAgICAgIGxldCBwcm9jZXNzQnVmZmVyID0gY29tYmluZWRCdWZmZXIuc3ViYXJyYXkoMCwgcHJvY2Vzc2FibGVCeXRlcyk7XG5cbiAgICAgIGlmICh0aGlzLnNlZWtUYXJnZXQgIT09IG51bGwpIHtcbiAgICAgICAgcHJvY2Vzc0J1ZmZlciA9IHRoaXMuaGFuZGxlU2Vlayhwcm9jZXNzQnVmZmVyKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuY3VycmVudFBvc2l0aW9uICs9IGZyYW1lQ291bnQ7XG4gICAgICB9XG5cbiAgICAgIGNhbGxiYWNrKG51bGwsIHByb2Nlc3NCdWZmZXIpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjYWxsYmFjayhlcnJvciBhcyBFcnJvcik7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIF9mbHVzaChcbiAgY2FsbGJhY2s6IChlcnJvcj86IEVycm9yIHwgbnVsbCwgZGF0YT86IEJ1ZmZlcikgPT4gdm9pZClcbiAgOiB2b2lkIHtcbiAgICBpZiAodGhpcy5idWZmZXIubGVuZ3RoID49IHRoaXMuYnl0ZXNQZXJGcmFtZSkge1xuICAgICAgY29uc3QgZnJhbWVDb3VudCA9IE1hdGguZmxvb3IodGhpcy5idWZmZXIubGVuZ3RoIC8gdGhpcy5ieXRlc1BlckZyYW1lKTtcbiAgICAgIGNvbnN0IHByb2Nlc3NhYmxlQnl0ZXMgPSBmcmFtZUNvdW50ICogdGhpcy5ieXRlc1BlckZyYW1lO1xuICAgICAgY2FsbGJhY2sobnVsbCwgdGhpcy5idWZmZXIuc3ViYXJyYXkoMCwgcHJvY2Vzc2FibGVCeXRlcykpO1xuICAgIH1cblxuICAgIGNhbGxiYWNrKCk7XG4gIH1cbn0iLCAiaW1wb3J0IHsgUENNVHJhbnNmb3JtZXIsIFBDTVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb20gJy4uL3V0aWxzJztcblxuZXhwb3J0IGludGVyZmFjZSBSZXZlcmJPcHRpb25zIGV4dGVuZHMgUENNVHJhbnNmb3JtZXJPcHRpb25zIHtcbiAgcm9vbVNpemU/OiBudW1iZXI7XG4gIGRhbXBpbmc/OiBudW1iZXI7XG4gIHdldExldmVsPzogbnVtYmVyO1xuICBkcnlMZXZlbD86IG51bWJlcjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBSZXZlcmJQYXJhbWV0ZXJzIHtcbiAgcm9vbVNpemU6IG51bWJlcjtcbiAgZGFtcGluZzogbnVtYmVyO1xuICB3ZXRMZXZlbDogbnVtYmVyO1xuICBkcnlMZXZlbDogbnVtYmVyO1xufVxuXG5leHBvcnQgY2xhc3MgUmV2ZXJiVHJhbnNmb3JtZXIgZXh0ZW5kcyBQQ01UcmFuc2Zvcm1lciB7XG4gIHByaXZhdGUgcm9vbVNpemU6IG51bWJlcjtcbiAgcHJpdmF0ZSBkYW1waW5nOiBudW1iZXI7XG4gIHByaXZhdGUgd2V0TGV2ZWw6IG51bWJlcjtcbiAgcHJpdmF0ZSBkcnlMZXZlbDogbnVtYmVyO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVsYXlMaW5lczogRmxvYXQzMkFycmF5W107XG4gIHByaXZhdGUgcmVhZG9ubHkgZGVsYXlMaW5lTGVuZ3RoOiBudW1iZXI7XG4gIHByaXZhdGUgZGVsYXlJbmRpY2VzOiBudW1iZXJbXTtcbiAgcHJpdmF0ZSByZWFkb25seSBudW1EZWxheUxpbmVzID0gODtcbiAgcHJpdmF0ZSByZWFkb25seSBmZWVkYmFjazogbnVtYmVyID0gMC44NDtcblxuICBjb25zdHJ1Y3RvcihvcHRpb25zOiBSZXZlcmJPcHRpb25zID0ge30pIHtcbiAgICBzdXBlcihvcHRpb25zKTtcblxuICAgIHRoaXMucm9vbVNpemUgPSBvcHRpb25zLnJvb21TaXplID8/IDAuNTtcbiAgICB0aGlzLmRhbXBpbmcgPSBvcHRpb25zLmRhbXBpbmcgPz8gMC41O1xuICAgIHRoaXMud2V0TGV2ZWwgPSBvcHRpb25zLndldExldmVsID8/IDAuMztcbiAgICB0aGlzLmRyeUxldmVsID0gb3B0aW9ucy5kcnlMZXZlbCA/PyAwLjc7XG5cbiAgICB0aGlzLmRlbGF5TGluZUxlbmd0aCA9IE1hdGguZmxvb3IodGhpcy5zYW1wbGVSYXRlICogMC4wNSk7XG4gICAgdGhpcy5kZWxheUxpbmVzID0gQXJyYXkuZnJvbShcbiAgICAgIHsgbGVuZ3RoOiB0aGlzLm51bURlbGF5TGluZXMgfSxcbiAgICAgICgpID0+IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5kZWxheUxpbmVMZW5ndGgpXG4gICAgKTtcbiAgICB0aGlzLmRlbGF5SW5kaWNlcyA9IEFycmF5KHRoaXMubnVtRGVsYXlMaW5lcykuZmlsbCgwKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRSb29tU2l6ZShzaXplOiBudW1iZXIpIHtcbiAgICB0aGlzLnJvb21TaXplID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgc2l6ZSkpO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXREYW1waW5nKGRhbXBpbmc6IG51bWJlcikge1xuICAgIHRoaXMuZGFtcGluZyA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGRhbXBpbmcpKTtcbiAgICB0aGlzLm9uVXBkYXRlKCk7XG4gIH1cblxuICBwdWJsaWMgc2V0V2V0TGV2ZWwobGV2ZWw6IG51bWJlcikge1xuICAgIHRoaXMud2V0TGV2ZWwgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBsZXZlbCkpO1xuICAgIHRoaXMub25VcGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBzZXREcnlMZXZlbChsZXZlbDogbnVtYmVyKSB7XG4gICAgdGhpcy5kcnlMZXZlbCA9IE1hdGgubWF4KDAsIE1hdGgubWluKDEsIGxldmVsKSk7XG4gICAgdGhpcy5vblVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIHNldFJldmVyYihvcHRpb25zOiBQYXJ0aWFsPFJldmVyYlBhcmFtZXRlcnM+KSB7XG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLnJvb21TaXplID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXRSb29tU2l6ZShvcHRpb25zLnJvb21TaXplKTtcbiAgICB9XG5cbiAgICBpZiAodHlwZW9mIG9wdGlvbnMuZGFtcGluZyA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuc2V0RGFtcGluZyhvcHRpb25zLmRhbXBpbmcpO1xuICAgIH1cblxuICAgIGlmICh0eXBlb2Ygb3B0aW9ucy53ZXRMZXZlbCA9PT0gJ251bWJlcicpIHtcbiAgICAgIHRoaXMuc2V0V2V0TGV2ZWwob3B0aW9ucy53ZXRMZXZlbCk7XG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBvcHRpb25zLmRyeUxldmVsID09PSAnbnVtYmVyJykge1xuICAgICAgdGhpcy5zZXREcnlMZXZlbChvcHRpb25zLmRyeUxldmVsKTtcbiAgICB9XG5cbiAgICB0aGlzLm9uVXBkYXRlKCk7XG5cbiAgICByZXR1cm4gdGhpcy5nZXRQYXJhbWV0ZXJzKCk7XG4gIH1cblxuICBwdWJsaWMgZ2V0UGFyYW1ldGVycygpOiBSZXZlcmJQYXJhbWV0ZXJzIHtcbiAgICByZXR1cm4ge1xuICAgICAgcm9vbVNpemU6IHRoaXMucm9vbVNpemUsXG4gICAgICBkYW1waW5nOiB0aGlzLmRhbXBpbmcsXG4gICAgICB3ZXRMZXZlbDogdGhpcy53ZXRMZXZlbCxcbiAgICAgIGRyeUxldmVsOiB0aGlzLmRyeUxldmVsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgcHJvY2Vzc1NhbXBsZShpbnB1dDogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkgcmV0dXJuIGlucHV0O1xuXG4gICAgY29uc3QgaW5wdXRGbG9hdCA9IGlucHV0IC8gdGhpcy5leHRyZW11bTtcbiAgICBsZXQgd2V0ID0gMDtcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5udW1EZWxheUxpbmVzOyBpKyspIHtcbiAgICAgIGNvbnN0IGRlbGF5TGluZSA9IHRoaXMuZGVsYXlMaW5lc1tpXTtcbiAgICAgIGNvbnN0IGRlbGF5SW5kZXggPSB0aGlzLmRlbGF5SW5kaWNlc1tpXTtcblxuICAgICAgY29uc3QgZGVsYXllZCA9IGRlbGF5TGluZVtkZWxheUluZGV4XTtcblxuICAgICAgY29uc3QgcHJvY2Vzc2VkID0gZGVsYXllZCAqIHRoaXMucm9vbVNpemUgKiAoMSAtIHRoaXMuZGFtcGluZyk7XG5cbiAgICAgIGRlbGF5TGluZVtkZWxheUluZGV4XSA9IGlucHV0RmxvYXQgKyBwcm9jZXNzZWQgKiB0aGlzLmZlZWRiYWNrO1xuXG4gICAgICB0aGlzLmRlbGF5SW5kaWNlc1tpXSA9IChkZWxheUluZGV4ICsgMSkgJSB0aGlzLmRlbGF5TGluZUxlbmd0aDtcblxuICAgICAgd2V0ICs9IHByb2Nlc3NlZDtcbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXQgPVxuICAgIGlucHV0RmxvYXQgKiB0aGlzLmRyeUxldmVsICsgd2V0ICogdGhpcy53ZXRMZXZlbCAvIHRoaXMubnVtRGVsYXlMaW5lcztcblxuICAgIHJldHVybiB0aGlzLmNsYW1wKE1hdGguZmxvb3Iob3V0cHV0ICogdGhpcy5leHRyZW11bSkpO1xuICB9XG5cbiAgcHVibGljIG92ZXJyaWRlIF90cmFuc2Zvcm0oXG4gIGNodW5rOiBCdWZmZXIsXG4gIGVuY29kaW5nOiBCdWZmZXJFbmNvZGluZyxcbiAgY2FsbGJhY2s6IChlcnJvcj86IEVycm9yIHwgbnVsbCwgZGF0YT86IEJ1ZmZlcikgPT4gdm9pZClcbiAgOiB2b2lkIHtcbiAgICBpZiAodGhpcy5kaXNhYmxlZCkge1xuICAgICAgY2FsbGJhY2sobnVsbCwgY2h1bmspO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG91dHB1dCA9IEJ1ZmZlci5hbGxvYyhjaHVuay5sZW5ndGgpO1xuXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjaHVuay5sZW5ndGg7IGkgKz0gdGhpcy5ieXRlcykge1xuICAgICAgY29uc3Qgc2FtcGxlID0gdGhpcy5fcmVhZEludChjaHVuaywgaSk7XG4gICAgICBjb25zdCBwcm9jZXNzZWQgPSB0aGlzLnByb2Nlc3NTYW1wbGUoc2FtcGxlKTtcbiAgICAgIHRoaXMuX3dyaXRlSW50KG91dHB1dCwgcHJvY2Vzc2VkLCBpKTtcbiAgICB9XG5cbiAgICBjYWxsYmFjayhudWxsLCBvdXRwdXQpO1xuICB9XG59IiwgImltcG9ydCB7IHR5cGUgUmVhZGFibGUsIHBpcGVsaW5lIH0gZnJvbSAnc3RyZWFtJztcbmltcG9ydCB7IEVxdWFsaXplclN0cmVhbSwgRXF1YWxpemVyU3RyZWFtT3B0aW9ucyB9IGZyb20gJy4vZXF1YWxpemVyJztcbmltcG9ydCB7XG4gIEF1ZGlvRmlsdGVyLFxuICBDb21wcmVzc29yT3B0aW9ucyxcbiAgQ29tcHJlc3NvclRyYW5zZm9ybWVyLFxuICBQQ01GaWx0ZXJlck9wdGlvbnMsXG4gIFBDTVJlc2FtcGxlcixcbiAgUENNUmVzYW1wbGVyT3B0aW9ucyxcbiAgUENNU2Vla2VyT3B0aW9ucyxcbiAgUENNU2Vla2VyVHJhbnNmb3JtZXIsXG4gIFJldmVyYk9wdGlvbnMsXG4gIFJldmVyYlRyYW5zZm9ybWVyIH0gZnJvbVxuJy4vYXVkaW8nO1xuaW1wb3J0IHsgQmlxdWFkU3RyZWFtLCBCaXF1YWRTdHJlYW1PcHRpb25zIH0gZnJvbSAnLi9iaXF1YWQnO1xuaW1wb3J0IHtcbiAgVm9sdW1lVHJhbnNmb3JtZXIsXG4gIFZvbHVtZVRyYW5zZm9ybWVyT3B0aW9ucyB9IGZyb21cbicuL2F1ZGlvL1ZvbHVtZVRyYW5zZm9ybWVyJztcblxuZXhwb3J0IGludGVyZmFjZSBEU1BGaWx0ZXJzUHJlc2V0IHtcbiAgZXF1YWxpemVyPzogRXF1YWxpemVyU3RyZWFtT3B0aW9ucztcbiAgZHNwPzogUENNRmlsdGVyZXJPcHRpb25zO1xuICBiaXF1YWQ/OiBCaXF1YWRTdHJlYW1PcHRpb25zO1xuICB2b2x1bWU/OiBWb2x1bWVUcmFuc2Zvcm1lck9wdGlvbnM7XG4gIHJlc2FtcGxlcj86IFBDTVJlc2FtcGxlck9wdGlvbnM7XG4gIGNvbXByZXNzb3I/OiBDb21wcmVzc29yT3B0aW9ucztcbiAgc2Vla2VyPzogUENNU2Vla2VyT3B0aW9ucztcbiAgcmV2ZXJiPzogUmV2ZXJiT3B0aW9ucztcbn1cblxuZXhwb3J0IGNsYXNzIEZpbHRlcnNDaGFpbiB7XG4gIHB1YmxpYyBlcXVhbGl6ZXI6IEVxdWFsaXplclN0cmVhbSB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgZmlsdGVyczogQXVkaW9GaWx0ZXIgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIGJpcXVhZDogQmlxdWFkU3RyZWFtIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyB2b2x1bWU6IFZvbHVtZVRyYW5zZm9ybWVyIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyByZXNhbXBsZXI6IFBDTVJlc2FtcGxlciB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgY29tcHJlc3NvcjogQ29tcHJlc3NvclRyYW5zZm9ybWVyIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyBzZWVrZXI6IFBDTVNlZWtlclRyYW5zZm9ybWVyIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyByZXZlcmI6IFJldmVyYlRyYW5zZm9ybWVyIHwgbnVsbCA9IG51bGw7XG4gIHB1YmxpYyBkZXN0aW5hdGlvbjogUmVhZGFibGUgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIHNvdXJjZTogUmVhZGFibGUgfCBudWxsID0gbnVsbDtcbiAgcHVibGljIG9uVXBkYXRlOiAoKSA9PiB1bmtub3duID0gKCkgPT4gbnVsbDtcbiAgcHVibGljIG9uRXJyb3I6IChlcnI6IEVycm9yKSA9PiB1bmtub3duID0gKCkgPT4gbnVsbDtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocHVibGljIHByZXNldHM6IERTUEZpbHRlcnNQcmVzZXQgPSB7fSkge31cblxuICBwdWJsaWMgY3JlYXRlKHNyYzogUmVhZGFibGUsIHByZXNldHM6IERTUEZpbHRlcnNQcmVzZXQgPSB0aGlzLnByZXNldHMpIHtcbiAgICB0aGlzLmRlc3Ryb3koKTtcblxuICAgIHRoaXMuc291cmNlID0gc3JjO1xuXG4gICAgY29uc3QgcmVzYW1wbGVyID0gIXByZXNldHMucmVzYW1wbGVyPy5kaXNhYmxlZCA/XG4gICAgbmV3IFBDTVJlc2FtcGxlcihwcmVzZXRzLnJlc2FtcGxlcikgOlxuICAgIG51bGw7XG5cbiAgICBjb25zdCBlcXVhbGl6ZXJTdHJlYW0gPSAhcHJlc2V0cy5lcXVhbGl6ZXI/LmRpc2FibGVkID9cbiAgICBuZXcgRXF1YWxpemVyU3RyZWFtKHByZXNldHMuZXF1YWxpemVyKSA6XG4gICAgbnVsbDtcblxuICAgIGNvbnN0IGRzcFN0cmVhbSA9ICFwcmVzZXRzLmRzcD8uZGlzYWJsZWQgP1xuICAgIG5ldyBBdWRpb0ZpbHRlcihwcmVzZXRzLmRzcCkgOlxuICAgIG51bGw7XG5cbiAgICBjb25zdCBiaXF1YWRTdHJlYW0gPSAhcHJlc2V0cy5iaXF1YWQ/LmRpc2FibGVkID9cbiAgICBuZXcgQmlxdWFkU3RyZWFtKHByZXNldHMuYmlxdWFkKSA6XG4gICAgbnVsbDtcblxuICAgIGNvbnN0IHZvbHVtZVRyYW5zZm9ybWVyID0gIXByZXNldHMudm9sdW1lPy5kaXNhYmxlZCA/XG4gICAgbmV3IFZvbHVtZVRyYW5zZm9ybWVyKHByZXNldHMudm9sdW1lKSA6XG4gICAgbnVsbDtcblxuICAgIGNvbnN0IGNvbXByZXNzb3IgPSAhcHJlc2V0cy5jb21wcmVzc29yPy5kaXNhYmxlZCA/XG4gICAgbmV3IENvbXByZXNzb3JUcmFuc2Zvcm1lcihwcmVzZXRzLmNvbXByZXNzb3IpIDpcbiAgICBudWxsO1xuXG4gICAgY29uc3Qgc2Vla2VyID0gIXByZXNldHMuc2Vla2VyPy5kaXNhYmxlZCA/XG4gICAgbmV3IFBDTVNlZWtlclRyYW5zZm9ybWVyKHByZXNldHMuc2Vla2VyKSA6XG4gICAgbnVsbDtcblxuICAgIGNvbnN0IHJldmVyYiA9ICFwcmVzZXRzLnJldmVyYj8uZGlzYWJsZWQgP1xuICAgIG5ldyBSZXZlcmJUcmFuc2Zvcm1lcihwcmVzZXRzLnJldmVyYikgOlxuICAgIG51bGw7XG5cbiAgICB0aGlzLnJlc2FtcGxlciA9IHJlc2FtcGxlcjtcbiAgICB0aGlzLmVxdWFsaXplciA9IGVxdWFsaXplclN0cmVhbTtcbiAgICB0aGlzLmZpbHRlcnMgPSBkc3BTdHJlYW07XG4gICAgdGhpcy5iaXF1YWQgPSBiaXF1YWRTdHJlYW07XG4gICAgdGhpcy52b2x1bWUgPSB2b2x1bWVUcmFuc2Zvcm1lcjtcbiAgICB0aGlzLmNvbXByZXNzb3IgPSBjb21wcmVzc29yO1xuICAgIHRoaXMuc2Vla2VyID0gc2Vla2VyO1xuICAgIHRoaXMucmV2ZXJiID0gcmV2ZXJiO1xuXG4gICAgLy8gdXBkYXRlIGxpc3RlbmVyc1xuICAgIGlmIChyZXNhbXBsZXIpIHJlc2FtcGxlci5vblVwZGF0ZSA9IHRoaXMub25VcGRhdGU7XG4gICAgaWYgKGVxdWFsaXplclN0cmVhbSkgZXF1YWxpemVyU3RyZWFtLm9uVXBkYXRlID0gdGhpcy5vblVwZGF0ZTtcbiAgICBpZiAoZHNwU3RyZWFtKSBkc3BTdHJlYW0ub25VcGRhdGUgPSB0aGlzLm9uVXBkYXRlO1xuICAgIGlmIChiaXF1YWRTdHJlYW0pIGJpcXVhZFN0cmVhbS5vblVwZGF0ZSA9IHRoaXMub25VcGRhdGU7XG4gICAgaWYgKHZvbHVtZVRyYW5zZm9ybWVyKSB2b2x1bWVUcmFuc2Zvcm1lci5vblVwZGF0ZSA9IHRoaXMub25VcGRhdGU7XG4gICAgaWYgKGNvbXByZXNzb3IpIGNvbXByZXNzb3Iub25VcGRhdGUgPSB0aGlzLm9uVXBkYXRlO1xuICAgIGlmIChzZWVrZXIpIHNlZWtlci5vblVwZGF0ZSA9IHRoaXMub25VcGRhdGU7XG4gICAgaWYgKHJldmVyYikgcmV2ZXJiLm9uVXBkYXRlID0gdGhpcy5vblVwZGF0ZTtcblxuICAgIGNvbnN0IGNoYWlucyA9IFtcbiAgICBzcmMsXG4gICAgcmVzYW1wbGVyLFxuICAgIGVxdWFsaXplclN0cmVhbSxcbiAgICByZXZlcmIsXG4gICAgZHNwU3RyZWFtLFxuICAgIGJpcXVhZFN0cmVhbSxcbiAgICBjb21wcmVzc29yLFxuICAgIHZvbHVtZVRyYW5zZm9ybWVyLFxuICAgIHNlZWtlcl0uXG4gICAgZmlsdGVyKEJvb2xlYW4pIGFzIFJlYWRvbmx5PFJlYWRhYmxlW10+O1xuXG4gICAgaWYgKCFjaGFpbnMubGVuZ3RoKSByZXR1cm4gc3JjO1xuXG4gICAgLy8gQHRzLWlnbm9yZVxuICAgIHRoaXMuZGVzdGluYXRpb24gPSBwaXBlbGluZSguLi5jaGFpbnMsIChlcnI6IEVycm9yIHwgbnVsbCkgPT4ge1xuICAgICAgaWYgKGVycikge1xuICAgICAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgaWYgKCFlcnIubWVzc2FnZS5pbmNsdWRlcygnRVJSX1NUUkVBTV9QUkVNQVRVUkVfQ0xPU0UnKSlcbiAgICAgICAgdGhpcy5vbkVycm9yKGVycik7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICB0aGlzLmRlc3RpbmF0aW9uIS5vbmNlKCdjbG9zZScsIHRoaXMuZGVzdHJveS5iaW5kKHRoaXMpKTtcblxuICAgIHJldHVybiB0aGlzLmRlc3RpbmF0aW9uIGFzIFJlYWRhYmxlO1xuICB9XG5cbiAgcHVibGljIGRlc3Ryb3koKSB7XG4gICAgLy8gY2xlYW51cFxuICAgIHRoaXMucmVzYW1wbGVyPy5kZXN0cm95KCk7XG4gICAgdGhpcy5lcXVhbGl6ZXI/LmRlc3Ryb3koKTtcbiAgICB0aGlzLmJpcXVhZD8uZGVzdHJveSgpO1xuICAgIHRoaXMuZmlsdGVycz8uZGVzdHJveSgpO1xuICAgIHRoaXMudm9sdW1lPy5kZXN0cm95KCk7XG4gICAgdGhpcy5jb21wcmVzc29yPy5kZXN0cm95KCk7XG4gICAgdGhpcy5zZWVrZXI/LmRlc3Ryb3koKTtcbiAgICB0aGlzLnJldmVyYj8uZGVzdHJveSgpO1xuICAgIHRoaXMuZGVzdGluYXRpb24/LmRlc3Ryb3koKTtcbiAgICB0aGlzLnNvdXJjZT8uZGVzdHJveSgpO1xuXG4gICAgLy8gcmVtb3ZlIGV2ZW50c1xuICAgIHRoaXMucmVzYW1wbGVyPy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLmVxdWFsaXplcj8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgdGhpcy5iaXF1YWQ/LnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIHRoaXMuZmlsdGVycz8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgdGhpcy52b2x1bWU/LnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIHRoaXMuY29tcHJlc3Nvcj8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG4gICAgdGhpcy5zZWVrZXI/LnJlbW92ZUFsbExpc3RlbmVycygpO1xuICAgIHRoaXMucmV2ZXJiPy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLmRlc3RpbmF0aW9uPy5yZW1vdmVBbGxMaXN0ZW5lcnMoKTtcbiAgICB0aGlzLnNvdXJjZT8ucmVtb3ZlQWxsTGlzdGVuZXJzKCk7XG5cbiAgICAvLyB1bnJlZlxuICAgIHRoaXMucmVzYW1wbGVyID0gbnVsbDtcbiAgICB0aGlzLmVxdWFsaXplciA9IG51bGw7XG4gICAgdGhpcy5iaXF1YWQgPSBudWxsO1xuICAgIHRoaXMuZmlsdGVycyA9IG51bGw7XG4gICAgdGhpcy52b2x1bWUgPSBudWxsO1xuICAgIHRoaXMuY29tcHJlc3NvciA9IG51bGw7XG4gICAgdGhpcy5zZWVrZXIgPSBudWxsO1xuICAgIHRoaXMucmV2ZXJiID0gbnVsbDtcbiAgICB0aGlzLmRlc3RpbmF0aW9uID0gbnVsbDtcbiAgICB0aGlzLnNvdXJjZSA9IG51bGw7XG4gIH1cbn0iLCAiXG5cblxuXG5cblxuZXhwb3J0IGNvbnN0IHZlcnNpb24gPSAvKiBAX19NQUNST19fIGdldFZlcnNpb24gKi9cIjcuMi4wXCI7Il0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7OztBQUFPLElBQU0sYUFBYTtBQUFBLEVBQ3hCLHlCQUF5QjtBQUFBLEVBQ3pCLG1CQUFtQjtBQUFBLEVBQ25CLFNBQVM7QUFBQSxFQUNULFVBQVU7QUFBQSxFQUNWLFVBQVU7QUFBQSxFQUNWLE9BQU87QUFBQSxFQUNQLFNBQVM7QUFBQSxFQUNULFVBQVU7QUFBQSxFQUNWLFdBQVc7QUFBQSxFQUNYLFdBQVc7QUFDYjtBQWNPLElBQU0sZ0JBQWdCLEtBQUs7QUFFM0IsSUFBTSxnQkFBTixNQUFNLGNBQWE7QUFBQSxFQVVqQixZQUFZLE1BQXlCO0FBUjVDO0FBQUEsd0JBQU8sTUFBSztBQUNaLHdCQUFPLE1BQUs7QUFHWjtBQUFBLHdCQUFPLE1BQUs7QUFDWix3QkFBTyxNQUFLO0FBQ1osd0JBQU8sTUFBSztBQUdWLFFBQUksTUFBTTtBQUNSLFdBQUssS0FBSyxLQUFLO0FBQ2YsV0FBSyxLQUFLLEtBQUs7QUFDZixXQUFLLEtBQUssS0FBSztBQUNmLFdBQUssS0FBSyxLQUFLO0FBQ2YsV0FBSyxLQUFLLEtBQUs7QUFBQSxJQUNqQjtBQUFBLEVBQ0Y7QUFBQSxFQUVBLE9BQWMsS0FDZCxRQUNBLGNBQ0EsWUFDQSxHQUNBLFNBQVMsS0FDVDtBQUNFLFFBQUksSUFBTSxhQUFhLGNBQWM7QUFDbkMsWUFBTSxJ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
|