es51922
Version:
Streaming Cyrustek ES51922 DMM data protocol implementation over serial
659 lines (561 loc) • 79 kB
JavaScript
import { take, tap, mapTo, concatMap, map } from 'rxjs/operators';
import { using, fromEvent, iif, of } from 'rxjs';
import { streamToRx, rxToStream } from 'rxjs-stream';
import ByteLength from '@serialport/parser-byte-length';
import KaitaiStream from 'kaitai-struct/KaitaiStream';
import { KaitaiStream as KaitaiStream$1 } from 'kaitai-struct';
import SerialPort from 'serialport';
import { config } from 'dotenv';
import createDebugger from 'debug';
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
function ownKeys(object, enumerableOnly) {
var keys = Object.keys(object);
if (Object.getOwnPropertySymbols) {
keys.push.apply(keys, Object.getOwnPropertySymbols(object));
}
if (enumerableOnly) keys = keys.filter(function (sym) {
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
});
return keys;
}
function _objectSpread2(target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i] != null ? arguments[i] : {};
if (i % 2) {
ownKeys(source, true).forEach(function (key) {
_defineProperty(target, key, source[key]);
});
} else if (Object.getOwnPropertyDescriptors) {
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
} else {
ownKeys(source).forEach(function (key) {
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
});
}
}
return target;
}
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
function createCommonjsModule(fn, module) {
return module = { exports: {} }, fn(module, module.exports), module.exports;
}
var es51922 = createCommonjsModule(function (module) {
// This is a generated file! Please edit source .ksy file and use kaitai-struct-compiler to rebuild
(function (root, factory) {
if ( module.exports) {
module.exports = factory(KaitaiStream);
} else {
root.Es51922 = factory(root.KaitaiStream);
}
})(commonjsGlobal, function (KaitaiStream) {
var Es51922 = function () {
Es51922.AdpRanges = Object.freeze({
ADP0: 0,
ADP1: 1,
ADP2: 2,
ADP3: 3,
ADP4: 4,
0: "ADP0",
1: "ADP1",
2: "ADP2",
3: "ADP3",
4: "ADP4"
});
Es51922.Functions = Object.freeze({
CURRENT_22A: 0,
DIODE: 1,
FREQ: 2,
RESISTANCE: 3,
TEMPERATURE: 4,
CONTINUITY: 5,
CAPACITANCE: 6,
CURRENT_MANUAL: 9,
VOLTAGE: 11,
CURRENT_MICROAMP: 13,
ADP: 14,
CURRENT_MILLIAMP: 15,
0: "CURRENT_22A",
1: "DIODE",
2: "FREQ",
3: "RESISTANCE",
4: "TEMPERATURE",
5: "CONTINUITY",
6: "CAPACITANCE",
9: "CURRENT_MANUAL",
11: "VOLTAGE",
13: "CURRENT_MICROAMP",
14: "ADP",
15: "CURRENT_MILLIAMP"
});
function Es51922(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root || this;
this._read();
}
Es51922.prototype._read = function () {
this.rawRange = this._io.readU1();
this.rawDigit0 = this._io.readU1();
this.rawDigit1 = this._io.readU1();
this.rawDigit2 = this._io.readU1();
this.rawDigit3 = this._io.readU1();
this.rawDigit4 = this._io.readU1();
this.rawFunc = this._io.readU1();
this.rawStatus = this._io.readU1();
this.rawOption0 = this._io.readU1();
this.rawOption1 = this._io.readU1();
this.rawOption2 = this._io.readU1();
this.rawOption3 = this._io.readU1();
this.eom = this._io.ensureFixedContents([13, 10]);
};
var Options = Es51922.Options = function () {
function Options(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root || this;
this._read();
}
Options.prototype._read = function () {};
Object.defineProperty(Options.prototype, 'hold', {
get: function () {
if (this._m_hold !== undefined) return this._m_hold;
this._m_hold = (this._parent.rawOption3 ^ 48 & 1) == 1;
return this._m_hold;
}
});
Object.defineProperty(Options.prototype, 'maximum', {
get: function () {
if (this._m_maximum !== undefined) return this._m_maximum;
this._m_maximum = (this._parent.rawOption0 ^ 48 & 3) == 1;
return this._m_maximum;
}
});
Object.defineProperty(Options.prototype, 'auto', {
get: function () {
if (this._m_auto !== undefined) return this._m_auto;
this._m_auto = (this._parent.rawOption2 ^ 48 & 1) == 1;
return this._m_auto;
}
});
Object.defineProperty(Options.prototype, 'peakMaximum', {
get: function () {
if (this._m_peakMaximum !== undefined) return this._m_peakMaximum;
this._m_peakMaximum = (this._parent.rawOption1 ^ 48 & 2) == 1;
return this._m_peakMaximum;
}
});
Object.defineProperty(Options.prototype, 'currentValue', {
get: function () {
if (this._m_currentValue !== undefined) return this._m_currentValue;
this._m_currentValue = (this._parent.rawOption0 ^ 48 & 0) == 1;
return this._m_currentValue;
}
});
Object.defineProperty(Options.prototype, 'vahz', {
get: function () {
if (this._m_vahz !== undefined) return this._m_vahz;
this._m_vahz = (this._parent.rawOption2 ^ 48 & 0) == 1;
return this._m_vahz;
}
});
Object.defineProperty(Options.prototype, 'lpf', {
get: function () {
if (this._m_lpf !== undefined) return this._m_lpf;
this._m_lpf = (this._parent.rawOption3 ^ 48 & 0) == 1;
return this._m_lpf;
}
});
Object.defineProperty(Options.prototype, 'minimum', {
get: function () {
if (this._m_minimum !== undefined) return this._m_minimum;
this._m_minimum = (this._parent.rawOption0 ^ 48 & 2) == 1;
return this._m_minimum;
}
});
Object.defineProperty(Options.prototype, 'acMode', {
get: function () {
if (this._m_acMode !== undefined) return this._m_acMode;
this._m_acMode = (this._parent.rawOption2 ^ 48 & 2) == 1 ? "current" : "voltage";
return this._m_acMode;
}
});
Object.defineProperty(Options.prototype, 'peakMinimum', {
get: function () {
if (this._m_peakMinimum !== undefined) return this._m_peakMinimum;
this._m_peakMinimum = (this._parent.rawOption1 ^ 48 & 1) == 1;
return this._m_peakMinimum;
}
});
Object.defineProperty(Options.prototype, 'dcMode', {
get: function () {
if (this._m_dcMode !== undefined) return this._m_dcMode;
this._m_dcMode = (this._parent.rawOption2 ^ 48 & 3) == 1 ? "current" : "voltage";
return this._m_dcMode;
}
});
Object.defineProperty(Options.prototype, 'relative', {
get: function () {
if (this._m_relative !== undefined) return this._m_relative;
this._m_relative = (this._parent.rawOption0 ^ 48 & 1) == 1;
return this._m_relative;
}
});
Object.defineProperty(Options.prototype, 'vbar', {
get: function () {
if (this._m_vbar !== undefined) return this._m_vbar;
this._m_vbar = (this._parent.rawOption3 ^ 48 & 2) == 1;
return this._m_vbar;
}
});
return Options;
}();
var BaseAdpRange = Es51922.BaseAdpRange = function () {
function BaseAdpRange(_io, _parent, _root, adpMode) {
this._io = _io;
this._parent = _parent;
this._root = _root || this;
this.adpMode = adpMode;
this._read();
}
BaseAdpRange.prototype._read = function () {};
return BaseAdpRange;
}();
var BaseFunc = Es51922.BaseFunc = function () {
function BaseFunc(_io, _parent, _root, baseUnit, baseRange, mode) {
this._io = _io;
this._parent = _parent;
this._root = _root || this;
this.baseUnit = baseUnit;
this.baseRange = baseRange;
this.mode = mode;
this._read();
}
BaseFunc.prototype._read = function () {};
return BaseFunc;
}();
var BaseRange = Es51922.BaseRange = function () {
function BaseRange(_io, _parent, _root, unit, multiplier, precision, mode) {
this._io = _io;
this._parent = _parent;
this._root = _root || this;
this.unit = unit;
this.multiplier = multiplier;
this.precision = precision;
this.mode = mode;
this._read();
}
BaseRange.prototype._read = function () {};
return BaseRange;
}();
var Status = Es51922.Status = function () {
function Status(_io, _parent, _root) {
this._io = _io;
this._parent = _parent;
this._root = _root || this;
this._read();
}
Status.prototype._read = function () {};
Object.defineProperty(Status.prototype, 'signMultiplier', {
get: function () {
if (this._m_signMultiplier !== undefined) return this._m_signMultiplier;
this._m_signMultiplier = (this._parent.rawStatus ^ 48 & 2) == 1 ? -1 : 1;
return this._m_signMultiplier;
}
});
Object.defineProperty(Status.prototype, 'batteryLow', {
get: function () {
if (this._m_batteryLow !== undefined) return this._m_batteryLow;
this._m_batteryLow = (this._parent.rawStatus ^ 48 & 1) == 1;
return this._m_batteryLow;
}
});
Object.defineProperty(Status.prototype, 'underload', {
get: function () {
if (this._m_underload !== undefined) return this._m_underload;
this._m_underload = (this._parent.rawOption1 ^ 48 & 2) == 1;
return this._m_underload;
}
});
Object.defineProperty(Status.prototype, 'degrees', {
get: function () {
if (this._m_degrees !== undefined) return this._m_degrees;
this._m_degrees = (this._parent.rawStatus ^ 48 & 3) == 1 ? "C" : "F";
return this._m_degrees;
}
});
Object.defineProperty(Status.prototype, 'overload', {
get: function () {
if (this._m_overload !== undefined) return this._m_overload;
this._m_overload = (this._parent.rawStatus ^ 48 & 0) == 1;
return this._m_overload;
}
});
Object.defineProperty(Status.prototype, 'operation', {
get: function () {
if (this._m_operation !== undefined) return this._m_operation;
this._m_operation = this.overload ? "overload" : this.underload ? "underload" : "normal";
return this._m_operation;
}
});
return Status;
}();
Object.defineProperty(Es51922.prototype, 'status', {
get: function () {
if (this._m_status !== undefined) return this._m_status;
this._m_status = new Status(this._io, this, this._root);
return this._m_status;
}
});
Object.defineProperty(Es51922.prototype, 'func', {
get: function () {
if (this._m_func !== undefined) return this._m_func;
this._m_func = this.rawFunc ^ 48;
return this._m_func;
}
});
Object.defineProperty(Es51922.prototype, 'digits', {
get: function () {
if (this._m_digits !== undefined) return this._m_digits;
var _pos = this._io.pos;
this._io.seek(1);
this._raw__m_digits = this._io.readBytes(5);
this._m_digits = KaitaiStream.processXorOne(this._raw__m_digits, 48);
this._io.seek(_pos);
return this._m_digits;
}
});
Object.defineProperty(Es51922.prototype, 'options', {
get: function () {
if (this._m_options !== undefined) return this._m_options;
this._m_options = new Options(this._io, this, this._root);
return this._m_options;
}
});
Object.defineProperty(Es51922.prototype, 'range', {
get: function () {
if (this._m_range !== undefined) return this._m_range;
switch (this.rawRange ^ 48 | (this.rawFunc ^ 48) << 4) {
case 177:
this._m_range = new BaseRange(this._io, this, this._root, "V", 1.0, 3, "voltage");
break;
case 0:
this._m_range = new BaseRange(this._io, this, this._root, "A", 1.0, 3, "current");
break;
case 146:
this._m_range = new BaseRange(this._io, this, this._root, "A", 1.0, 2, "current");
break;
case 224:
this._m_range = new BaseAdpRange(this._io, this, this._root, Es51922.AdpRanges.ADP0);
break;
case 35:
this._m_range = new BaseRange(this._io, this, this._root, "kHz", 1000.0, 2, "frequency");
break;
case 32:
this._m_range = new BaseRange(this._io, this, this._root, "Hz", 1.0, 2, "frequency");
break;
case 96:
this._m_range = new BaseRange(this._io, this, this._root, "nF", 1E-9, 3, "capacitance");
break;
case 209:
this._m_range = new BaseRange(this._io, this, this._root, "\xb5A", 0.000001, 1, "current");
break;
case 97:
this._m_range = new BaseRange(this._io, this, this._root, "nF", 1E-9, 2, "capacitance");
break;
case 145:
this._m_range = new BaseRange(this._io, this, this._root, "A", 1.0, 3, "current");
break;
case 52:
this._m_range = new BaseRange(this._io, this, this._root, "M\u03a9", 1000000.0, 4, "resistance");
break;
case 101:
this._m_range = new BaseRange(this._io, this, this._root, "mF", 0.001, 4, "capacitance");
break;
case 144:
this._m_range = new BaseRange(this._io, this, this._root, "A", 1.0, 4, "current");
break;
case 100:
this._m_range = new BaseRange(this._io, this, this._root, "\xb5F", 0.000001, 2, "capacitance");
break;
case 98:
this._m_range = new BaseRange(this._io, this, this._root, "\xb5F", 0.000001, 4, "capacitance");
break;
case 208:
this._m_range = new BaseRange(this._io, this, this._root, "\xb5A", 0.000001, 2, "current");
break;
case 33:
this._m_range = new BaseRange(this._io, this, this._root, "Hz", 1.0, 1, "frequency");
break;
case 103:
this._m_range = new BaseRange(this._io, this, this._root, "mF", 0.001, 2, "capacitance");
break;
case 99:
this._m_range = new BaseRange(this._io, this, this._root, "\xb5F", 0.000001, 3, "capacitance");
break;
case 180:
this._m_range = new BaseRange(this._io, this, this._root, "mV", 0.001, 2, "voltage");
break;
case 51:
this._m_range = new BaseRange(this._io, this, this._root, "k\u03a9", 1000.0, 2, "resistance");
break;
case 227:
this._m_range = new BaseAdpRange(this._io, this, this._root, Es51922.AdpRanges.ADP3);
break;
case 48:
this._m_range = new BaseRange(this._io, this, this._root, "\u03a9", 1.0, 2, "resistance");
break;
case 178:
this._m_range = new BaseRange(this._io, this, this._root, "V", 1.0, 2, "voltage");
break;
case 53:
this._m_range = new BaseRange(this._io, this, this._root, "M\u03a9", 1000000.0, 3, "resistance");
break;
case 176:
this._m_range = new BaseRange(this._io, this, this._root, "V", 1.0, 4, "voltage");
break;
case 38:
this._m_range = new BaseRange(this._io, this, this._root, "MHz", 1000000.0, 2, "frequency");
break;
case 148:
this._m_range = new BaseRange(this._io, this, this._root, "A", 1.0, 0, "current");
break;
case 241:
this._m_range = new BaseRange(this._io, this, this._root, "mA", 0.001, 2, "current");
break;
case 226:
this._m_range = new BaseAdpRange(this._io, this, this._root, Es51922.AdpRanges.ADP2);
break;
case 179:
this._m_range = new BaseRange(this._io, this, this._root, "V", 1.0, 1, "voltage");
break;
case 240:
this._m_range = new BaseRange(this._io, this, this._root, "mA", 0.001, 3, "current");
break;
case 225:
this._m_range = new BaseAdpRange(this._io, this, this._root, Es51922.AdpRanges.ADP1);
break;
case 37:
this._m_range = new BaseRange(this._io, this, this._root, "MHz", 1000000.0, 3, "frequency");
break;
case 36:
this._m_range = new BaseRange(this._io, this, this._root, "MHz", 1000000.0, 4, "frequency");
break;
case 16:
this._m_range = new BaseRange(this._io, this, this._root, "V", 1.0, 4, "diode");
break;
case 147:
this._m_range = new BaseRange(this._io, this, this._root, "A", 1.0, 1, "current");
break;
case 80:
this._m_range = new BaseRange(this._io, this, this._root, "\u03a9", 1.0, 2, "continuity");
break;
case 102:
this._m_range = new BaseRange(this._io, this, this._root, "mF", 0.001, 3, "capacitance");
break;
case 49:
this._m_range = new BaseRange(this._io, this, this._root, "k\u03a9", 1000.0, 4, "resistance");
break;
case 34:
this._m_range = new BaseRange(this._io, this, this._root, "kHz", 1000.0, 3, "frequency");
break;
case 54:
this._m_range = new BaseRange(this._io, this, this._root, "M\u03a9", 1000000.0, 2, "resistance");
break;
case 228:
this._m_range = new BaseAdpRange(this._io, this, this._root, Es51922.AdpRanges.ADP4);
break;
case 50:
this._m_range = new BaseRange(this._io, this, this._root, "k\u03a9", 1000.0, 3, "resistance");
break;
}
return this._m_range;
}
});
Object.defineProperty(Es51922.prototype, 'precision', {
get: function () {
if (this._m_precision !== undefined) return this._m_precision;
this._m_precision = this.range.precision == 0 ? 1.0 : this.range.precision == 1 ? 0.1 : this.range.precision == 2 ? 0.01 : this.range.precision == 3 ? 0.001 : 0.0001;
return this._m_precision;
}
});
Object.defineProperty(Es51922.prototype, 'value', {
get: function () {
if (this._m_value !== undefined) return this._m_value;
if (this.func != Es51922.Functions.TEMPERATURE && this.func != Es51922.Functions.ADP) {
this._m_value = ((this.rawDigit0 ^ 48) * 10000 + (this.rawDigit1 ^ 48) * 1000 + (this.rawDigit2 ^ 48) * 100 + (this.rawDigit3 ^ 48) * 10 + (this.rawDigit4 ^ 48)) * this.range.multiplier * this.precision * this.status.signMultiplier;
}
return this._m_value;
}
});
return Es51922;
}();
return Es51922;
});
});
config();
const debug = createDebugger('es51922');
const DEFAULT_PORT = '/dev/ttyUSB0';
const fromEventOnce = (...args) => fromEvent(...args).pipe(take(1));
const createProtocolStream = buf => new es51922(new KaitaiStream$1(buf));
const createFixedPrecisionProxy = protocolStream => new Proxy(protocolStream, {
get(target, prop, receiver) {
const value = Reflect.get(target, prop, receiver);
return prop === 'value' ? parseFloat(value.toFixed(target.range.precision)) : value;
}
});
const parse = () => observable => observable.pipe(tap(buf => debug(`received Buffer`, buf)), map(buf => createFixedPrecisionProxy(createProtocolStream(buf))));
const createSerialPortSubscriber = serialPort => {
const unsubscribe = () => {
debug(`request received to close port at ${serialPort.path}`);
if (serialPort.isOpen) {
serialPort.close();
} else {
debug(`port at ${serialPort.path} was already closed`);
}
};
return new Proxy(serialPort, {
get: (target, prop, receiver) => {
return prop === 'unsubscribe' ? unsubscribe : Reflect.get(target, prop, receiver);
}
});
};
const fromSerialPort = (port = process.env.ES51922_PORT || DEFAULT_PORT, opts = {}) => using(() => {
const serialPort = createSerialPortSubscriber(new SerialPort(port, _objectSpread2({
baudRate: 19200,
dataBits: 7,
parity: 'odd'
}, opts, {
autoOpen: false
})));
debug(`instantiated SerialPort at path ${port}`);
return serialPort;
}, serialPort => {
debug(`opening port at path ${port}`);
serialPort.open();
return fromEventOnce(serialPort, 'open').pipe(tap(() => {
debug(`port at ${serialPort.path} open`);
serialPort.set({
rts: false
});
}), mapTo(serialPort));
});
const fromES51922 = (port = process.env.ES51922_PORT || DEFAULT_PORT) => iif(() => typeof port === 'string', fromSerialPort(port), of(port)).pipe(concatMap(serialPort => streamToRx(serialPort.pipe(new ByteLength({
length: 14
})))), parse());
const readES51922Stream = (...args) => rxToStream(fromES51922(...args), {
objectMode: true
});
export { DEFAULT_PORT, fromES51922, fromSerialPort, readES51922Stream };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXM1MTkyMi5lc20uanMiLCJzb3VyY2VzIjpbIi4uL3ZlbmRvci9lczUxOTIyLmpzIiwiLi4vc3JjL2luZGV4LmpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8vIFRoaXMgaXMgYSBnZW5lcmF0ZWQgZmlsZSEgUGxlYXNlIGVkaXQgc291cmNlIC5rc3kgZmlsZSBhbmQgdXNlIGthaXRhaS1zdHJ1Y3QtY29tcGlsZXIgdG8gcmVidWlsZFxuXG4oZnVuY3Rpb24gKHJvb3QsIGZhY3RvcnkpIHtcbiAgaWYgKHR5cGVvZiBkZWZpbmUgPT09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCkge1xuICAgIGRlZmluZShbJ2thaXRhaS1zdHJ1Y3QvS2FpdGFpU3RyZWFtJ10sIGZhY3RvcnkpO1xuICB9IGVsc2UgaWYgKHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnICYmIG1vZHVsZS5leHBvcnRzKSB7XG4gICAgbW9kdWxlLmV4cG9ydHMgPSBmYWN0b3J5KHJlcXVpcmUoJ2thaXRhaS1zdHJ1Y3QvS2FpdGFpU3RyZWFtJykpO1xuICB9IGVsc2Uge1xuICAgIHJvb3QuRXM1MTkyMiA9IGZhY3Rvcnkocm9vdC5LYWl0YWlTdHJlYW0pO1xuICB9XG59KHRoaXMsIGZ1bmN0aW9uIChLYWl0YWlTdHJlYW0pIHtcbnZhciBFczUxOTIyID0gKGZ1bmN0aW9uKCkge1xuICBFczUxOTIyLkFkcFJhbmdlcyA9IE9iamVjdC5mcmVlemUoe1xuICAgIEFEUDA6IDAsXG4gICAgQURQMTogMSxcbiAgICBBRFAyOiAyLFxuICAgIEFEUDM6IDMsXG4gICAgQURQNDogNCxcblxuICAgIDA6IFwiQURQMFwiLFxuICAgIDE6IFwiQURQMVwiLFxuICAgIDI6IFwiQURQMlwiLFxuICAgIDM6IFwiQURQM1wiLFxuICAgIDQ6IFwiQURQNFwiLFxuICB9KTtcblxuICBFczUxOTIyLkZ1bmN0aW9ucyA9IE9iamVjdC5mcmVlemUoe1xuICAgIENVUlJFTlRfMjJBOiAwLFxuICAgIERJT0RFOiAxLFxuICAgIEZSRVE6IDIsXG4gICAgUkVTSVNUQU5DRTogMyxcbiAgICBURU1QRVJBVFVSRTogNCxcbiAgICBDT05USU5VSVRZOiA1LFxuICAgIENBUEFDSVRBTkNFOiA2LFxuICAgIENVUlJFTlRfTUFOVUFMOiA5LFxuICAgIFZPTFRBR0U6IDExLFxuICAgIENVUlJFTlRfTUlDUk9BTVA6IDEzLFxuICAgIEFEUDogMTQsXG4gICAgQ1VSUkVOVF9NSUxMSUFNUDogMTUsXG5cbiAgICAwOiBcIkNVUlJFTlRfMjJBXCIsXG4gICAgMTogXCJESU9ERVwiLFxuICAgIDI6IFwiRlJFUVwiLFxuICAgIDM6IFwiUkVTSVNUQU5DRVwiLFxuICAgIDQ6IFwiVEVNUEVSQVRVUkVcIixcbiAgICA1OiBcIkNPTlRJTlVJVFlcIixcbiAgICA2OiBcIkNBUEFDSVRBTkNFXCIsXG4gICAgOTogXCJDVVJSRU5UX01BTlVBTFwiLFxuICAgIDExOiBcIlZPTFRBR0VcIixcbiAgICAxMzogXCJDVVJSRU5UX01JQ1JPQU1QXCIsXG4gICAgMTQ6IFwiQURQXCIsXG4gICAgMTU6IFwiQ1VSUkVOVF9NSUxMSUFNUFwiLFxuICB9KTtcblxuICBmdW5jdGlvbiBFczUxOTIyKF9pbywgX3BhcmVudCwgX3Jvb3QpIHtcbiAgICB0aGlzLl9pbyA9IF9pbztcbiAgICB0aGlzLl9wYXJlbnQgPSBfcGFyZW50O1xuICAgIHRoaXMuX3Jvb3QgPSBfcm9vdCB8fCB0aGlzO1xuXG4gICAgdGhpcy5fcmVhZCgpO1xuICB9XG4gIEVzNTE5MjIucHJvdG90eXBlLl9yZWFkID0gZnVuY3Rpb24oKSB7XG4gICAgdGhpcy5yYXdSYW5nZSA9IHRoaXMuX2lvLnJlYWRVMSgpO1xuICAgIHRoaXMucmF3RGlnaXQwID0gdGhpcy5faW8ucmVhZFUxKCk7XG4gICAgdGhpcy5yYXdEaWdpdDEgPSB0aGlzLl9pby5yZWFkVTEoKTtcbiAgICB0aGlzLnJhd0RpZ2l0MiA9IHRoaXMuX2lvLnJlYWRVMSgpO1xuICAgIHRoaXMucmF3RGlnaXQzID0gdGhpcy5faW8ucmVhZFUxKCk7XG4gICAgdGhpcy5yYXdEaWdpdDQgPSB0aGlzLl9pby5yZWFkVTEoKTtcbiAgICB0aGlzLnJhd0Z1bmMgPSB0aGlzLl9pby5yZWFkVTEoKTtcbiAgICB0aGlzLnJhd1N0YXR1cyA9IHRoaXMuX2lvLnJlYWRVMSgpO1xuICAgIHRoaXMucmF3T3B0aW9uMCA9IHRoaXMuX2lvLnJlYWRVMSgpO1xuICAgIHRoaXMucmF3T3B0aW9uMSA9IHRoaXMuX2lvLnJlYWRVMSgpO1xuICAgIHRoaXMucmF3T3B0aW9uMiA9IHRoaXMuX2lvLnJlYWRVMSgpO1xuICAgIHRoaXMucmF3T3B0aW9uMyA9IHRoaXMuX2lvLnJlYWRVMSgpO1xuICAgIHRoaXMuZW9tID0gdGhpcy5faW8uZW5zdXJlRml4ZWRDb250ZW50cyhbMTMsIDEwXSk7XG4gIH1cblxuICB2YXIgT3B0aW9ucyA9IEVzNTE5MjIuT3B0aW9ucyA9IChmdW5jdGlvbigpIHtcbiAgICBmdW5jdGlvbiBPcHRpb25zKF9pbywgX3BhcmVudCwgX3Jvb3QpIHtcbiAgICAgIHRoaXMuX2lvID0gX2lvO1xuICAgICAgdGhpcy5fcGFyZW50ID0gX3BhcmVudDtcbiAgICAgIHRoaXMuX3Jvb3QgPSBfcm9vdCB8fCB0aGlzO1xuXG4gICAgICB0aGlzLl9yZWFkKCk7XG4gICAgfVxuICAgIE9wdGlvbnMucHJvdG90eXBlLl9yZWFkID0gZnVuY3Rpb24oKSB7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPcHRpb25zLnByb3RvdHlwZSwgJ2hvbGQnLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fbV9ob2xkICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgcmV0dXJuIHRoaXMuX21faG9sZDtcbiAgICAgICAgdGhpcy5fbV9ob2xkID0gKHRoaXMuX3BhcmVudC5yYXdPcHRpb24zIF4gKDQ4ICYgMSkpID09IDE7XG4gICAgICAgIHJldHVybiB0aGlzLl9tX2hvbGQ7XG4gICAgICB9XG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE9wdGlvbnMucHJvdG90eXBlLCAnbWF4aW11bScsIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9tX21heGltdW0gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICByZXR1cm4gdGhpcy5fbV9tYXhpbXVtO1xuICAgICAgICB0aGlzLl9tX21heGltdW0gPSAodGhpcy5fcGFyZW50LnJhd09wdGlvbjAgXiAoNDggJiAzKSkgPT0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fbWF4aW11bTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoT3B0aW9ucy5wcm90b3R5cGUsICdhdXRvJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX21fYXV0byAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX2F1dG87XG4gICAgICAgIHRoaXMuX21fYXV0byA9ICh0aGlzLl9wYXJlbnQucmF3T3B0aW9uMiBeICg0OCAmIDEpKSA9PSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV9hdXRvO1xuICAgICAgfVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPcHRpb25zLnByb3RvdHlwZSwgJ3BlYWtNYXhpbXVtJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX21fcGVha01heGltdW0gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICByZXR1cm4gdGhpcy5fbV9wZWFrTWF4aW11bTtcbiAgICAgICAgdGhpcy5fbV9wZWFrTWF4aW11bSA9ICh0aGlzLl9wYXJlbnQucmF3T3B0aW9uMSBeICg0OCAmIDIpKSA9PSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV9wZWFrTWF4aW11bTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoT3B0aW9ucy5wcm90b3R5cGUsICdjdXJyZW50VmFsdWUnLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fbV9jdXJyZW50VmFsdWUgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICByZXR1cm4gdGhpcy5fbV9jdXJyZW50VmFsdWU7XG4gICAgICAgIHRoaXMuX21fY3VycmVudFZhbHVlID0gKHRoaXMuX3BhcmVudC5yYXdPcHRpb24wIF4gKDQ4ICYgMCkpID09IDE7XG4gICAgICAgIHJldHVybiB0aGlzLl9tX2N1cnJlbnRWYWx1ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoT3B0aW9ucy5wcm90b3R5cGUsICd2YWh6Jywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX21fdmFoeiAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX3ZhaHo7XG4gICAgICAgIHRoaXMuX21fdmFoeiA9ICh0aGlzLl9wYXJlbnQucmF3T3B0aW9uMiBeICg0OCAmIDApKSA9PSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV92YWh6O1xuICAgICAgfVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPcHRpb25zLnByb3RvdHlwZSwgJ2xwZicsIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9tX2xwZiAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX2xwZjtcbiAgICAgICAgdGhpcy5fbV9scGYgPSAodGhpcy5fcGFyZW50LnJhd09wdGlvbjMgXiAoNDggJiAwKSkgPT0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fbHBmO1xuICAgICAgfVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPcHRpb25zLnByb3RvdHlwZSwgJ21pbmltdW0nLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fbV9taW5pbXVtICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgcmV0dXJuIHRoaXMuX21fbWluaW11bTtcbiAgICAgICAgdGhpcy5fbV9taW5pbXVtID0gKHRoaXMuX3BhcmVudC5yYXdPcHRpb24wIF4gKDQ4ICYgMikpID09IDE7XG4gICAgICAgIHJldHVybiB0aGlzLl9tX21pbmltdW07XG4gICAgICB9XG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE9wdGlvbnMucHJvdG90eXBlLCAnYWNNb2RlJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX21fYWNNb2RlICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgcmV0dXJuIHRoaXMuX21fYWNNb2RlO1xuICAgICAgICB0aGlzLl9tX2FjTW9kZSA9ICgodGhpcy5fcGFyZW50LnJhd09wdGlvbjIgXiAoNDggJiAyKSkgPT0gMSA/IFwiY3VycmVudFwiIDogXCJ2b2x0YWdlXCIpO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV9hY01vZGU7XG4gICAgICB9XG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KE9wdGlvbnMucHJvdG90eXBlLCAncGVha01pbmltdW0nLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fbV9wZWFrTWluaW11bSAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX3BlYWtNaW5pbXVtO1xuICAgICAgICB0aGlzLl9tX3BlYWtNaW5pbXVtID0gKHRoaXMuX3BhcmVudC5yYXdPcHRpb24xIF4gKDQ4ICYgMSkpID09IDE7XG4gICAgICAgIHJldHVybiB0aGlzLl9tX3BlYWtNaW5pbXVtO1xuICAgICAgfVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPcHRpb25zLnByb3RvdHlwZSwgJ2RjTW9kZScsIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9tX2RjTW9kZSAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX2RjTW9kZTtcbiAgICAgICAgdGhpcy5fbV9kY01vZGUgPSAoKHRoaXMuX3BhcmVudC5yYXdPcHRpb24yIF4gKDQ4ICYgMykpID09IDEgPyBcImN1cnJlbnRcIiA6IFwidm9sdGFnZVwiKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fZGNNb2RlO1xuICAgICAgfVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShPcHRpb25zLnByb3RvdHlwZSwgJ3JlbGF0aXZlJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX21fcmVsYXRpdmUgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICByZXR1cm4gdGhpcy5fbV9yZWxhdGl2ZTtcbiAgICAgICAgdGhpcy5fbV9yZWxhdGl2ZSA9ICh0aGlzLl9wYXJlbnQucmF3T3B0aW9uMCBeICg0OCAmIDEpKSA9PSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV9yZWxhdGl2ZTtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoT3B0aW9ucy5wcm90b3R5cGUsICd2YmFyJywge1xuICAgICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgICAgaWYgKHRoaXMuX21fdmJhciAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX3ZiYXI7XG4gICAgICAgIHRoaXMuX21fdmJhciA9ICh0aGlzLl9wYXJlbnQucmF3T3B0aW9uMyBeICg0OCAmIDIpKSA9PSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV92YmFyO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIE9wdGlvbnM7XG4gIH0pKCk7XG5cbiAgdmFyIEJhc2VBZHBSYW5nZSA9IEVzNTE5MjIuQmFzZUFkcFJhbmdlID0gKGZ1bmN0aW9uKCkge1xuICAgIGZ1bmN0aW9uIEJhc2VBZHBSYW5nZShfaW8sIF9wYXJlbnQsIF9yb290LCBhZHBNb2RlKSB7XG4gICAgICB0aGlzLl9pbyA9IF9pbztcbiAgICAgIHRoaXMuX3BhcmVudCA9IF9wYXJlbnQ7XG4gICAgICB0aGlzLl9yb290ID0gX3Jvb3QgfHwgdGhpcztcbiAgICAgIHRoaXMuYWRwTW9kZSA9IGFkcE1vZGU7XG5cbiAgICAgIHRoaXMuX3JlYWQoKTtcbiAgICB9XG4gICAgQmFzZUFkcFJhbmdlLnByb3RvdHlwZS5fcmVhZCA9IGZ1bmN0aW9uKCkge1xuICAgIH1cblxuICAgIHJldHVybiBCYXNlQWRwUmFuZ2U7XG4gIH0pKCk7XG5cbiAgdmFyIEJhc2VGdW5jID0gRXM1MTkyMi5CYXNlRnVuYyA9IChmdW5jdGlvbigpIHtcbiAgICBmdW5jdGlvbiBCYXNlRnVuYyhfaW8sIF9wYXJlbnQsIF9yb290LCBiYXNlVW5pdCwgYmFzZVJhbmdlLCBtb2RlKSB7XG4gICAgICB0aGlzLl9pbyA9IF9pbztcbiAgICAgIHRoaXMuX3BhcmVudCA9IF9wYXJlbnQ7XG4gICAgICB0aGlzLl9yb290ID0gX3Jvb3QgfHwgdGhpcztcbiAgICAgIHRoaXMuYmFzZVVuaXQgPSBiYXNlVW5pdDtcbiAgICAgIHRoaXMuYmFzZVJhbmdlID0gYmFzZVJhbmdlO1xuICAgICAgdGhpcy5tb2RlID0gbW9kZTtcblxuICAgICAgdGhpcy5fcmVhZCgpO1xuICAgIH1cbiAgICBCYXNlRnVuYy5wcm90b3R5cGUuX3JlYWQgPSBmdW5jdGlvbigpIHtcbiAgICB9XG5cbiAgICByZXR1cm4gQmFzZUZ1bmM7XG4gIH0pKCk7XG5cbiAgdmFyIEJhc2VSYW5nZSA9IEVzNTE5MjIuQmFzZVJhbmdlID0gKGZ1bmN0aW9uKCkge1xuICAgIGZ1bmN0aW9uIEJhc2VSYW5nZShfaW8sIF9wYXJlbnQsIF9yb290LCB1bml0LCBtdWx0aXBsaWVyLCBwcmVjaXNpb24sIG1vZGUpIHtcbiAgICAgIHRoaXMuX2lvID0gX2lvO1xuICAgICAgdGhpcy5fcGFyZW50ID0gX3BhcmVudDtcbiAgICAgIHRoaXMuX3Jvb3QgPSBfcm9vdCB8fCB0aGlzO1xuICAgICAgdGhpcy51bml0ID0gdW5pdDtcbiAgICAgIHRoaXMubXVsdGlwbGllciA9IG11bHRpcGxpZXI7XG4gICAgICB0aGlzLnByZWNpc2lvbiA9IHByZWNpc2lvbjtcbiAgICAgIHRoaXMubW9kZSA9IG1vZGU7XG5cbiAgICAgIHRoaXMuX3JlYWQoKTtcbiAgICB9XG4gICAgQmFzZVJhbmdlLnByb3RvdHlwZS5fcmVhZCA9IGZ1bmN0aW9uKCkge1xuICAgIH1cblxuICAgIHJldHVybiBCYXNlUmFuZ2U7XG4gIH0pKCk7XG5cbiAgdmFyIFN0YXR1cyA9IEVzNTE5MjIuU3RhdHVzID0gKGZ1bmN0aW9uKCkge1xuICAgIGZ1bmN0aW9uIFN0YXR1cyhfaW8sIF9wYXJlbnQsIF9yb290KSB7XG4gICAgICB0aGlzLl9pbyA9IF9pbztcbiAgICAgIHRoaXMuX3BhcmVudCA9IF9wYXJlbnQ7XG4gICAgICB0aGlzLl9yb290ID0gX3Jvb3QgfHwgdGhpcztcblxuICAgICAgdGhpcy5fcmVhZCgpO1xuICAgIH1cbiAgICBTdGF0dXMucHJvdG90eXBlLl9yZWFkID0gZnVuY3Rpb24oKSB7XG4gICAgfVxuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTdGF0dXMucHJvdG90eXBlLCAnc2lnbk11bHRpcGxpZXInLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fbV9zaWduTXVsdGlwbGllciAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX3NpZ25NdWx0aXBsaWVyO1xuICAgICAgICB0aGlzLl9tX3NpZ25NdWx0aXBsaWVyID0gKCh0aGlzLl9wYXJlbnQucmF3U3RhdHVzIF4gKDQ4ICYgMikpID09IDEgPyAtMSA6IDEpO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV9zaWduTXVsdGlwbGllcjtcbiAgICAgIH1cbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoU3RhdHVzLnByb3RvdHlwZSwgJ2JhdHRlcnlMb3cnLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fbV9iYXR0ZXJ5TG93ICE9PSB1bmRlZmluZWQpXG4gICAgICAgICAgcmV0dXJuIHRoaXMuX21fYmF0dGVyeUxvdztcbiAgICAgICAgdGhpcy5fbV9iYXR0ZXJ5TG93ID0gKHRoaXMuX3BhcmVudC5yYXdTdGF0dXMgXiAoNDggJiAxKSkgPT0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fYmF0dGVyeUxvdztcbiAgICAgIH1cbiAgICB9KTtcbiAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkoU3RhdHVzLnByb3RvdHlwZSwgJ3VuZGVybG9hZCcsIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9tX3VuZGVybG9hZCAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX3VuZGVybG9hZDtcbiAgICAgICAgdGhpcy5fbV91bmRlcmxvYWQgPSAodGhpcy5fcGFyZW50LnJhd09wdGlvbjEgXiAoNDggJiAyKSkgPT0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fdW5kZXJsb2FkO1xuICAgICAgfVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTdGF0dXMucHJvdG90eXBlLCAnZGVncmVlcycsIHtcbiAgICAgIGdldDogZnVuY3Rpb24oKSB7XG4gICAgICAgIGlmICh0aGlzLl9tX2RlZ3JlZXMgIT09IHVuZGVmaW5lZClcbiAgICAgICAgICByZXR1cm4gdGhpcy5fbV9kZWdyZWVzO1xuICAgICAgICB0aGlzLl9tX2RlZ3JlZXMgPSAoKHRoaXMuX3BhcmVudC5yYXdTdGF0dXMgXiAoNDggJiAzKSkgPT0gMSA/IFwiQ1wiIDogXCJGXCIpO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV9kZWdyZWVzO1xuICAgICAgfVxuICAgIH0pO1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShTdGF0dXMucHJvdG90eXBlLCAnb3ZlcmxvYWQnLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fbV9vdmVybG9hZCAhPT0gdW5kZWZpbmVkKVxuICAgICAgICAgIHJldHVybiB0aGlzLl9tX292ZXJsb2FkO1xuICAgICAgICB0aGlzLl9tX292ZXJsb2FkID0gKHRoaXMuX3BhcmVudC5yYXdTdGF0dXMgXiAoNDggJiAwKSkgPT0gMTtcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fb3ZlcmxvYWQ7XG4gICAgICB9XG4gICAgfSk7XG4gICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFN0YXR1cy5wcm90b3R5cGUsICdvcGVyYXRpb24nLCB7XG4gICAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgICBpZiAodGhpcy5fbV9vcGVyYXRpb24gIT09IHVuZGVmaW5lZClcbiAgICAgICAgICByZXR1cm4gdGhpcy5fbV9vcGVyYXRpb247XG4gICAgICAgIHRoaXMuX21fb3BlcmF0aW9uID0gKHRoaXMub3ZlcmxvYWQgPyBcIm92ZXJsb2FkXCIgOiAodGhpcy51bmRlcmxvYWQgPyBcInVuZGVybG9hZFwiIDogXCJub3JtYWxcIikpO1xuICAgICAgICByZXR1cm4gdGhpcy5fbV9vcGVyYXRpb247XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICByZXR1cm4gU3RhdHVzO1xuICB9KSgpO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXM1MTkyMi5wcm90b3R5cGUsICdzdGF0dXMnLCB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLl9tX3N0YXR1cyAhPT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gdGhpcy5fbV9zdGF0dXM7XG4gICAgICB0aGlzLl9tX3N0YXR1cyA9IG5ldyBTdGF0dXModGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QpO1xuICAgICAgcmV0dXJuIHRoaXMuX21fc3RhdHVzO1xuICAgIH1cbiAgfSk7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFczUxOTIyLnByb3RvdHlwZSwgJ2Z1bmMnLCB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLl9tX2Z1bmMgIT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fZnVuYztcbiAgICAgIHRoaXMuX21fZnVuYyA9ICh0aGlzLnJhd0Z1bmMgXiA0OCk7XG4gICAgICByZXR1cm4gdGhpcy5fbV9mdW5jO1xuICAgIH1cbiAgfSk7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShFczUxOTIyLnByb3RvdHlwZSwgJ2RpZ2l0cycsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHRoaXMuX21fZGlnaXRzICE9PSB1bmRlZmluZWQpXG4gICAgICAgIHJldHVybiB0aGlzLl9tX2RpZ2l0cztcbiAgICAgIHZhciBfcG9zID0gdGhpcy5faW8ucG9zO1xuICAgICAgdGhpcy5faW8uc2VlaygxKTtcbiAgICAgIHRoaXMuX3Jhd19fbV9kaWdpdHMgPSB0aGlzLl9pby5yZWFkQnl0ZXMoNSk7XG4gICAgICB0aGlzLl9tX2RpZ2l0cyA9IEthaXRhaVN0cmVhbS5wcm9jZXNzWG9yT25lKHRoaXMuX3Jhd19fbV9kaWdpdHMsIDQ4KTtcbiAgICAgIHRoaXMuX2lvLnNlZWsoX3Bvcyk7XG4gICAgICByZXR1cm4gdGhpcy5fbV9kaWdpdHM7XG4gICAgfVxuICB9KTtcbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KEVzNTE5MjIucHJvdG90eXBlLCAnb3B0aW9ucycsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHRoaXMuX21fb3B0aW9ucyAhPT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gdGhpcy5fbV9vcHRpb25zO1xuICAgICAgdGhpcy5fbV9vcHRpb25zID0gbmV3IE9wdGlvbnModGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QpO1xuICAgICAgcmV0dXJuIHRoaXMuX21fb3B0aW9ucztcbiAgICB9XG4gIH0pO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXM1MTkyMi5wcm90b3R5cGUsICdyYW5nZScsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHRoaXMuX21fcmFuZ2UgIT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fcmFuZ2U7XG4gICAgICBzd2l0Y2ggKCgodGhpcy5yYXdSYW5nZSBeIDQ4KSB8ICgodGhpcy5yYXdGdW5jIF4gNDgpIDw8IDQpKSkge1xuICAgICAgY2FzZSAxNzc6XG4gICAgICAgIHRoaXMuX21fcmFuZ2UgPSBuZXcgQmFzZVJhbmdlKHRoaXMuX2lvLCB0aGlzLCB0aGlzLl9yb290LCBcIlZcIiwgMS4wLCAzLCBcInZvbHRhZ2VcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAwOlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJBXCIsIDEuMCwgMywgXCJjdXJyZW50XCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTQ2OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJBXCIsIDEuMCwgMiwgXCJjdXJyZW50XCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjI0OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VBZHBSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgRXM1MTkyMi5BZHBSYW5nZXMuQURQMCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzNTpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwia0h6XCIsIDEwMDAuMCwgMiwgXCJmcmVxdWVuY3lcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzMjpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiSHpcIiwgMS4wLCAyLCBcImZyZXF1ZW5jeVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDk2OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJuRlwiLCAxRS05LCAzLCBcImNhcGFjaXRhbmNlXCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjA5OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJcXHhiNUFcIiwgMC4wMDAwMDEsIDEsIFwiY3VycmVudFwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDk3OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJuRlwiLCAxRS05LCAyLCBcImNhcGFjaXRhbmNlXCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTQ1OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJBXCIsIDEuMCwgMywgXCJjdXJyZW50XCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNTI6XG4gICAgICAgIHRoaXMuX21fcmFuZ2UgPSBuZXcgQmFzZVJhbmdlKHRoaXMuX2lvLCB0aGlzLCB0aGlzLl9yb290LCBcIk1cXHUwM2E5XCIsIDEwMDAwMDAuMCwgNCwgXCJyZXNpc3RhbmNlXCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTAxOlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJtRlwiLCAwLjAwMSwgNCwgXCJjYXBhY2l0YW5jZVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE0NDpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiQVwiLCAxLjAsIDQsIFwiY3VycmVudFwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDEwMDpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiXFx4YjVGXCIsIDAuMDAwMDAxLCAyLCBcImNhcGFjaXRhbmNlXCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgOTg6XG4gICAgICAgIHRoaXMuX21fcmFuZ2UgPSBuZXcgQmFzZVJhbmdlKHRoaXMuX2lvLCB0aGlzLCB0aGlzLl9yb290LCBcIlxceGI1RlwiLCAwLjAwMDAwMSwgNCwgXCJjYXBhY2l0YW5jZVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDIwODpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiXFx4YjVBXCIsIDAuMDAwMDAxLCAyLCBcImN1cnJlbnRcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzMzpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiSHpcIiwgMS4wLCAxLCBcImZyZXF1ZW5jeVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDEwMzpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwibUZcIiwgMC4wMDEsIDIsIFwiY2FwYWNpdGFuY2VcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA5OTpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiXFx4YjVGXCIsIDAuMDAwMDAxLCAzLCBcImNhcGFjaXRhbmNlXCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTgwOlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJtVlwiLCAwLjAwMSwgMiwgXCJ2b2x0YWdlXCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgNTE6XG4gICAgICAgIHRoaXMuX21fcmFuZ2UgPSBuZXcgQmFzZVJhbmdlKHRoaXMuX2lvLCB0aGlzLCB0aGlzLl9yb290LCBcImtcXHUwM2E5XCIsIDEwMDAuMCwgMiwgXCJyZXNpc3RhbmNlXCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjI3OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VBZHBSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgRXM1MTkyMi5BZHBSYW5nZXMuQURQMyk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA0ODpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiXFx1MDNhOVwiLCAxLjAsIDIsIFwicmVzaXN0YW5jZVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE3ODpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiVlwiLCAxLjAsIDIsIFwidm9sdGFnZVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDUzOlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJNXFx1MDNhOVwiLCAxMDAwMDAwLjAsIDMsIFwicmVzaXN0YW5jZVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE3NjpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiVlwiLCAxLjAsIDQsIFwidm9sdGFnZVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDM4OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJNSHpcIiwgMTAwMDAwMC4wLCAyLCBcImZyZXF1ZW5jeVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDE0ODpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiQVwiLCAxLjAsIDAsIFwiY3VycmVudFwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDI0MTpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwibUFcIiwgMC4wMDEsIDIsIFwiY3VycmVudFwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDIyNjpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlQWRwUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIEVzNTE5MjIuQWRwUmFuZ2VzLkFEUDIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMTc5OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJWXCIsIDEuMCwgMSwgXCJ2b2x0YWdlXCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjQwOlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJtQVwiLCAwLjAwMSwgMywgXCJjdXJyZW50XCIpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgMjI1OlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VBZHBSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgRXM1MTkyMi5BZHBSYW5nZXMuQURQMSk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzNzpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiTUh6XCIsIDEwMDAwMDAuMCwgMywgXCJmcmVxdWVuY3lcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzNjpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiTUh6XCIsIDEwMDAwMDAuMCwgNCwgXCJmcmVxdWVuY3lcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAxNjpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiVlwiLCAxLjAsIDQsIFwiZGlvZGVcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAxNDc6XG4gICAgICAgIHRoaXMuX21fcmFuZ2UgPSBuZXcgQmFzZVJhbmdlKHRoaXMuX2lvLCB0aGlzLCB0aGlzLl9yb290LCBcIkFcIiwgMS4wLCAxLCBcImN1cnJlbnRcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA4MDpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiXFx1MDNhOVwiLCAxLjAsIDIsIFwiY29udGludWl0eVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDEwMjpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwibUZcIiwgMC4wMDEsIDMsIFwiY2FwYWNpdGFuY2VcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA0OTpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwia1xcdTAzYTlcIiwgMTAwMC4wLCA0LCBcInJlc2lzdGFuY2VcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAzNDpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwia0h6XCIsIDEwMDAuMCwgMywgXCJmcmVxdWVuY3lcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSA1NDpcbiAgICAgICAgdGhpcy5fbV9yYW5nZSA9IG5ldyBCYXNlUmFuZ2UodGhpcy5faW8sIHRoaXMsIHRoaXMuX3Jvb3QsIFwiTVxcdTAzYTlcIiwgMTAwMDAwMC4wLCAyLCBcInJlc2lzdGFuY2VcIik7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAyMjg6XG4gICAgICAgIHRoaXMuX21fcmFuZ2UgPSBuZXcgQmFzZUFkcFJhbmdlKHRoaXMuX2lvLCB0aGlzLCB0aGlzLl9yb290LCBFczUxOTIyLkFkcFJhbmdlcy5BRFA0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlIDUwOlxuICAgICAgICB0aGlzLl9tX3JhbmdlID0gbmV3IEJhc2VSYW5nZSh0aGlzLl9pbywgdGhpcywgdGhpcy5fcm9vdCwgXCJrXFx1MDNhOVwiLCAxMDAwLjAsIDMsIFwicmVzaXN0YW5jZVwiKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fbV9yYW5nZTtcbiAgICB9XG4gIH0pO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXM1MTkyMi5wcm90b3R5cGUsICdwcmVjaXNpb24nLCB7XG4gICAgZ2V0OiBmdW5jdGlvbigpIHtcbiAgICAgIGlmICh0aGlzLl9tX3ByZWNpc2lvbiAhPT0gdW5kZWZpbmVkKVxuICAgICAgICByZXR1cm4gdGhpcy5fbV9wcmVjaXNpb247XG4gICAgICB0aGlzLl9tX3ByZWNpc2lvbiA9ICh0aGlzLnJhbmdlLnByZWNpc2lvbiA9PSAwID8gMS4wIDogKHRoaXMucmFuZ2UucHJlY2lzaW9uID09IDEgPyAwLjEgOiAodGhpcy5yYW5nZS5wcmVjaXNpb24gPT0gMiA/IDAuMDEgOiAodGhpcy5yYW5nZS5wcmVjaXNpb24gPT0gMyA/IDAuMDAxIDogMC4wMDAxKSkpKTtcbiAgICAgIHJldHVybiB0aGlzLl9tX3ByZWNpc2lvbjtcbiAgICB9XG4gIH0pO1xuICBPYmplY3QuZGVmaW5lUHJvcGVydHkoRXM1MTkyMi5wcm90b3R5cGUsICd2YWx1ZScsIHtcbiAgICBnZXQ6IGZ1bmN0aW9uKCkge1xuICAgICAgaWYgKHRoaXMuX21fdmFsdWUgIT09IHVuZGVmaW5lZClcbiAgICAgICAgcmV0dXJuIHRoaXMuX21fdmFsdWU7XG4gICAgICBpZiAoICgodGhpcy5mdW5jICE9IEVzNTE5MjIuRnVuY3Rpb25zLlRFTVBFUkFUVVJFKSAmJiAodGhpcy5mdW5jICE9IEVzNTE5MjIuRnVuY3Rpb25zLkFEUCkpICkge1xuICAgICAgICB0aGlzLl9tX3ZhbHVlID0gKCgoKCgoKCgodGhpcy5yYXdEaWdpdDAgXiA0OCkgKiAxMDAwMCkgKyAoKHRoaXMucmF3RGlnaXQxIF4gNDgpICogMTAwMCkpICsgKCh0aGlzLnJhd0RpZ2l0MiBeIDQ4KSAqIDEwMCkpICsgKCh0aGlzLnJhd0RpZ2l0MyBeIDQ4KSAqIDEwKSkgKyAodGhpcy5yYXdEaWdpdDQgXiA0OCkpICogdGhpcy5yYW5nZS5tdWx0aXBsaWVyKSAqIHRoaXMucHJlY2lzaW9uKSAqIHRoaXMuc3RhdHVzLnNpZ25NdWx0aXBsaWVyKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiB0aGlzLl9tX3ZhbHVlO1xuICAgIH1cbiAgfSk7XG5cbiAgcmV0dXJuIEVzNTE5MjI7XG59KSgpO1xucmV0dXJuIEVzNTE5MjI7XG59KSk7XG4iLCJpbXBvcnQge2NvbmNhdE1hcCwgbWFwLCBtYXBUbywgdGFrZSwgdGFwfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge2Zyb21FdmVudCwgdXNpbmcsIG9mLCBpaWZ9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtyeFRvU3RyZWFtLCBzdHJlYW1Ub1J4fSBmcm9tICdyeGpzLXN0cmVhbSc7XG5cbmltcG9ydCBCeXRlTGVuZ3RoIGZyb20gJ0BzZXJpYWxwb3J0L3BhcnNlci1ieXRlLWxlbmd0aCc7XG5pbXBvcnQgRVM1MTkyMiBmcm9tICcuLi92ZW5kb3IvZXM1MTkyMi5qcyc7XG5pbXBvcnQge0thaXRhaVN0cmVhbX0gZnJvbSAna2FpdGFpLXN0cnVjdCc7XG5pbXBvcnQgU2VyaWFsUG9ydCBmcm9tICdzZXJpYWxwb3J0JztcbmltcG9ydCB7Y29uZmlnIGFzIGRvdGVudkNvbmZpZ30gZnJvbSAnZG90ZW52JztcbmltcG9ydCBjcmVhdGVEZWJ1Z2dlciBmcm9tICdkZWJ1Zyc7XG5cbmRvdGVudkNvbmZpZygpO1xuXG5jb25zdCBkZWJ1ZyA9IGNyZWF0ZURlYnVnZ2VyKCdlczUxOTIyJyk7XG5cbmV4cG9ydCBjb25zdCBERUZBVUxUX1BPUlQgPSAnL2Rldi90dHlVU0IwJztcblxuY29uc3QgZnJvbUV2ZW50T25jZSA9ICguLi5hcmdzKSA9PiBmcm9tRXZlbnQoLi4uYXJncykucGlwZSh0YWtlKDEpKTtcblxuY29uc3QgY3JlYXRlUHJvdG9jb2xTdHJlYW0gPSBidWYgPT4gbmV3IEVTNTE5MjIobmV3IEthaXRhaVN0cmVhbShidWYpKTtcblxuY29uc3QgY3JlYXRlRml4ZWRQcmVjaXNpb25Qcm94eSA9IHByb3RvY29sU3RyZWFtID0+XG4gIG5ldyBQcm94eShwcm90b2NvbFN0cmVhbSwge1xuICAgIGdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IFJlZmxlY3QuZ2V0KHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpO1xuICAgICAgcmV0dXJuIHByb3AgPT09ICd2YWx1ZSdcbiAgICAgICAgPyBwYXJzZUZsb2F0KHZhbHVlLnRvRml4ZWQodGFyZ2V0LnJhbmdlLnByZWNpc2lvbikpXG4gICAgICAgIDogdmFsdWU7XG4gICAgfVxuICB9KTtcblxuY29uc3QgcGFyc2UgPSAoKSA9PiBvYnNlcnZhYmxlID0+XG4gIG9ic2VydmFibGUucGlwZShcbiAgICB0YXAoYnVmID0+IGRlYnVnKGByZWNlaXZlZCBCdWZmZXJgLCBidWYpKSxcbiAgICBtYXAoYnVmID0+IGNyZWF0ZUZpeGVkUHJlY2lzaW9uUHJveHkoY3JlYXRlUHJvdG9jb2xTdHJlYW0oYnVmKSkpXG4gICk7XG5cbmNvbnN0IGNyZWF0ZVNlcmlhbFBvcnRTdWJzY3JpYmVyID0gc2VyaWFsUG9ydCA9PiB7XG4gIGNvbnN0IHVuc3Vic2NyaWJlID0gKCkgPT4ge1xuICAgIGRlYnVnKGByZXF1ZXN0IHJlY2VpdmVkIHRvIGNsb3NlIHBvcnQgYXQgJHtzZXJpYWxQb3J0LnBhdGh9YCk7XG4gICAgaWYgKHNlcmlhbFBvcnQuaXNPcGVuKSB7XG4gICAgICBzZXJpYWxQb3J0LmNsb3NlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlYnVnKGBwb3J0IGF0ICR7c2VyaWFsUG9ydC5wYXRofSB3YXMgYWxyZWFkeSBjbG9zZWRgKTtcbiAgICB9XG4gIH07XG4gIHJldHVybiBuZXcgUHJveHkoc2VyaWFsUG9ydCwge1xuICAgIGdldDogKHRhcmdldCwgcHJvcCwgcmVjZWl2ZXIpID0+IHtcbiAgICAgIHJldHVybiBwcm9wID09PSAndW5zdWJzY3JpYmUnXG4gICAgICAgID8gdW5zdWJzY3JpYmVcbiAgICAgICAgOiBSZWZsZWN0LmdldCh0YXJnZXQsIHByb3AsIHJlY2VpdmVyKTtcbiAgICB9XG4gIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGZyb21TZXJpYWxQb3J0ID0gKFxuICBwb3J0ID0gcHJvY2Vzcy5lbnYuRVM1MTkyMl9QT1JUIHx8IERFRkFVTFRfUE9SVCxcbiAgb3B0cyA9IHt9XG4pID0+XG4gIHVzaW5nKFxuICAgICgpID0+IHtcbiAgICAgIGNvbnN0IHNlcmlhbFBvcnQgPSBjcmVhdGVTZXJpYWxQb3J0U3Vic2NyaWJlcihcbiAgICAgICAgbmV3IFNlcmlhbFBvcnQocG9ydCwge1xuICAgICAgICAgIGJhdWRSYXRlOiAxOTIwMCxcbiAgICAgICAgICBkYXRhQml0czogNyxcbiAgICAgICAgICBwYXJpdHk6ICdvZGQnLFxuICAgICAgICAgIC4uLm9wdHMsXG4gICAgICAgICAgYXV0b09wZW46IGZhbHNlXG4gICAgICAgIH0pXG4gICAgICApO1xuICAgICAgZGVidWcoYGluc3RhbnRpYXRlZCBTZXJpYWxQb3J0IGF0IHBhdGggJHtwb3J0fWApO1xuICAgICAgcmV0dXJuIHNlcmlhbFBvcnQ7XG4gICAgfSxcbiAgICBzZXJpYWxQb3J0ID0+IHtcbiAgICAgIGRlYnVnKGBvcGVuaW5nIHBvcnQgYXQgcGF0aCAke3BvcnR9YCk7XG4gICAgICBzZXJpYWxQb3J0Lm9wZW4oKTtcbiAgICAgIHJldHVybiBmcm9tRXZlbnRPbmNlKHNlcmlhbFBvcnQsICdvcGVuJykucGlwZShcbiAgICAgICAgdGFwKCgpID0+IHtcbiAgICAgICAgICBkZWJ1ZyhgcG9ydCBhdCAke3NlcmlhbFBvcnQucGF0aH0gb3BlbmApO1xuICAgICAgICAgIHNlcmlhbFBvcnQuc2V0KHtydHM6