!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.swaggerAjaxClient=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { var fn = queue.shift(); fn(); } } }, true); return function nextTick(fn) { queue.push(fn); window.postMessage('process-tick', '*'); }; } return function nextTick(fn) { setTimeout(fn, 0); }; })(); process.title = 'browser'; process.browser = true; process.env = {}; process.argv = []; function noop() {} process.on = noop; process.addListener = noop; process.once = noop; process.off = noop; process.removeListener = noop; process.removeAllListeners = noop; process.emit = noop; process.binding = function (name) { throw new Error('process.binding is not supported'); } // TODO(shtylman) process.cwd = function () { return '/' }; process.chdir = function (dir) { throw new Error('process.chdir is not supported'); }; },{}],2:[function(_dereq_,module,exports){ "use strict"; var Promise = _dereq_("./promise/promise").Promise; var polyfill = _dereq_("./promise/polyfill").polyfill; exports.Promise = Promise; exports.polyfill = polyfill; },{"./promise/polyfill":6,"./promise/promise":7}],3:[function(_dereq_,module,exports){ "use strict"; /* global toString */ var isArray = _dereq_("./utils").isArray; var isFunction = _dereq_("./utils").isFunction; /** Returns a promise that is fulfilled when all the given promises have been fulfilled, or rejected if any of them become rejected. The return promise is fulfilled with an array that gives all the values in the order they were passed in the `promises` array argument. Example: ```javascript var promise1 = RSVP.resolve(1); var promise2 = RSVP.resolve(2); var promise3 = RSVP.resolve(3); var promises = [ promise1, promise2, promise3 ]; RSVP.all(promises).then(function(array){ // The array here would be [ 1, 2, 3 ]; }); ``` If any of the `promises` given to `RSVP.all` are rejected, the first promise that is rejected will be given as an argument to the returned promises's rejection handler. For example: Example: ```javascript var promise1 = RSVP.resolve(1); var promise2 = RSVP.reject(new Error("2")); var promise3 = RSVP.reject(new Error("3")); var promises = [ promise1, promise2, promise3 ]; RSVP.all(promises).then(function(array){ // Code here never runs because there are rejected promises! }, function(error) { // error.message === "2" }); ``` @method all @for RSVP @param {Array} promises @param {String} label @return {Promise} promise that is fulfilled when all `promises` have been fulfilled, or rejected if any of them become rejected. */ function all(promises) { /*jshint validthis:true */ var Promise = this; if (!isArray(promises)) { throw new TypeError('You must pass an array to all.'); } return new Promise(function(resolve, reject) { var results = [], remaining = promises.length, promise; if (remaining === 0) { resolve([]); } function resolver(index) { return function(value) { resolveAll(index, value); }; } function resolveAll(index, value) { results[index] = value; if (--remaining === 0) { resolve(results); } } for (var i = 0; i < promises.length; i++) { promise = promises[i]; if (promise && isFunction(promise.then)) { promise.then(resolver(i), reject); } else { resolveAll(i, promise); } } }); } exports.all = all; },{"./utils":11}],4:[function(_dereq_,module,exports){ (function (process,global){ "use strict"; var browserGlobal = (typeof window !== 'undefined') ? window : {}; var BrowserMutationObserver = browserGlobal.MutationObserver || browserGlobal.WebKitMutationObserver; var local = (typeof global !== 'undefined') ? global : (this === undefined? window:this); // node function useNextTick() { return function() { process.nextTick(flush); }; } function useMutationObserver() { var iterations = 0; var observer = new BrowserMutationObserver(flush); var node = document.createTextNode(''); observer.observe(node, { characterData: true }); return function() { node.data = (iterations = ++iterations % 2); }; } function useSetTimeout() { return function() { local.setTimeout(flush, 1); }; } var queue = []; function flush() { for (var i = 0; i < queue.length; i++) { var tuple = queue[i]; var callback = tuple[0], arg = tuple[1]; callback(arg); } queue = []; } var scheduleFlush; // Decide what async method to use to triggering processing of queued callbacks: if (typeof process !== 'undefined' && {}.toString.call(process) === '[object process]') { scheduleFlush = useNextTick(); } else if (BrowserMutationObserver) { scheduleFlush = useMutationObserver(); } else { scheduleFlush = useSetTimeout(); } function asap(callback, arg) { var length = queue.push([callback, arg]); if (length === 1) { // If length is 1, that means that we need to schedule an async flush. // If additional callbacks are queued before the queue is flushed, they // will be processed by this flush that we are scheduling. scheduleFlush(); } } exports.asap = asap; }).call(this,_dereq_("0yPD3/"),typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"0yPD3/":1}],5:[function(_dereq_,module,exports){ "use strict"; var config = { instrument: false }; function configure(name, value) { if (arguments.length === 2) { config[name] = value; } else { return config[name]; } } exports.config = config; exports.configure = configure; },{}],6:[function(_dereq_,module,exports){ (function (global){ "use strict"; /*global self*/ var RSVPPromise = _dereq_("./promise").Promise; var isFunction = _dereq_("./utils").isFunction; function polyfill() { var local; if (typeof global !== 'undefined') { local = global; } else if (typeof window !== 'undefined' && window.document) { local = window; } else { local = self; } var es6PromiseSupport = "Promise" in local && // Some of these methods are missing from // Firefox/Chrome experimental implementations "resolve" in local.Promise && "reject" in local.Promise && "all" in local.Promise && "race" in local.Promise && // Older version of the spec had a resolver object // as the arg rather than a function (function() { var resolve; new local.Promise(function(r) { resolve = r; }); return isFunction(resolve); }()); if (!es6PromiseSupport) { local.Promise = RSVPPromise; } } exports.polyfill = polyfill; }).call(this,typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {}) },{"./promise":7,"./utils":11}],7:[function(_dereq_,module,exports){ "use strict"; var config = _dereq_("./config").config; var configure = _dereq_("./config").configure; var objectOrFunction = _dereq_("./utils").objectOrFunction; var isFunction = _dereq_("./utils").isFunction; var now = _dereq_("./utils").now; var all = _dereq_("./all").all; var race = _dereq_("./race").race; var staticResolve = _dereq_("./resolve").resolve; var staticReject = _dereq_("./reject").reject; var asap = _dereq_("./asap").asap; var counter = 0; config.async = asap; // default async is asap; function Promise(resolver) { if (!isFunction(resolver)) { throw new TypeError('You must pass a resolver function as the first argument to the promise constructor'); } if (!(this instanceof Promise)) { throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function."); } this._subscribers = []; invokeResolver(resolver, this); } function invokeResolver(resolver, promise) { function resolvePromise(value) { resolve(promise, value); } function rejectPromise(reason) { reject(promise, reason); } try { resolver(resolvePromise, rejectPromise); } catch(e) { rejectPromise(e); } } function invokeCallback(settled, promise, callback, detail) { var hasCallback = isFunction(callback), value, error, succeeded, failed; if (hasCallback) { try { value = callback(detail); succeeded = true; } catch(e) { failed = true; error = e; } } else { value = detail; succeeded = true; } if (handleThenable(promise, value)) { return; } else if (hasCallback && succeeded) { resolve(promise, value); } else if (failed) { reject(promise, error); } else if (settled === FULFILLED) { resolve(promise, value); } else if (settled === REJECTED) { reject(promise, value); } } var PENDING = void 0; var SEALED = 0; var FULFILLED = 1; var REJECTED = 2; function subscribe(parent, child, onFulfillment, onRejection) { var subscribers = parent._subscribers; var length = subscribers.length; subscribers[length] = child; subscribers[length + FULFILLED] = onFulfillment; subscribers[length + REJECTED] = onRejection; } function publish(promise, settled) { var child, callback, subscribers = promise._subscribers, detail = promise._detail; for (var i = 0; i < subscribers.length; i += 3) { child = subscribers[i]; callback = subscribers[i + settled]; invokeCallback(settled, child, callback, detail); } promise._subscribers = null; } Promise.prototype = { constructor: Promise, _state: undefined, _detail: undefined, _subscribers: undefined, then: function(onFulfillment, onRejection) { var promise = this; var thenPromise = new this.constructor(function() {}); if (this._state) { var callbacks = arguments; config.async(function invokePromiseCallback() { invokeCallback(promise._state, thenPromise, callbacks[promise._state - 1], promise._detail); }); } else { subscribe(this, thenPromise, onFulfillment, onRejection); } return thenPromise; }, 'catch': function(onRejection) { return this.then(null, onRejection); } }; Promise.all = all; Promise.race = race; Promise.resolve = staticResolve; Promise.reject = staticReject; function handleThenable(promise, value) { var then = null, resolved; try { if (promise === value) { throw new TypeError("A promises callback cannot return that same promise."); } if (objectOrFunction(value)) { then = value.then; if (isFunction(then)) { then.call(value, function(val) { if (resolved) { return true; } resolved = true; if (value !== val) { resolve(promise, val); } else { fulfill(promise, val); } }, function(val) { if (resolved) { return true; } resolved = true; reject(promise, val); }); return true; } } } catch (error) { if (resolved) { return true; } reject(promise, error); return true; } return false; } function resolve(promise, value) { if (promise === value) { fulfill(promise, value); } else if (!handleThenable(promise, value)) { fulfill(promise, value); } } function fulfill(promise, value) { if (promise._state !== PENDING) { return; } promise._state = SEALED; promise._detail = value; config.async(publishFulfillment, promise); } function reject(promise, reason) { if (promise._state !== PENDING) { return; } promise._state = SEALED; promise._detail = reason; config.async(publishRejection, promise); } function publishFulfillment(promise) { publish(promise, promise._state = FULFILLED); } function publishRejection(promise) { publish(promise, promise._state = REJECTED); } exports.Promise = Promise; },{"./all":3,"./asap":4,"./config":5,"./race":8,"./reject":9,"./resolve":10,"./utils":11}],8:[function(_dereq_,module,exports){ "use strict"; /* global toString */ var isArray = _dereq_("./utils").isArray; /** `RSVP.race` allows you to watch a series of promises and act as soon as the first promise given to the `promises` argument fulfills or rejects. Example: ```javascript var promise1 = new RSVP.Promise(function(resolve, reject){ setTimeout(function(){ resolve("promise 1"); }, 200); }); var promise2 = new RSVP.Promise(function(resolve, reject){ setTimeout(function(){ resolve("promise 2"); }, 100); }); RSVP.race([promise1, promise2]).then(function(result){ // result === "promise 2" because it was resolved before promise1 // was resolved. }); ``` `RSVP.race` is deterministic in that only the state of the first completed promise matters. For example, even if other promises given to the `promises` array argument are resolved, but the first completed promise has become rejected before the other promises became fulfilled, the returned promise will become rejected: ```javascript var promise1 = new RSVP.Promise(function(resolve, reject){ setTimeout(function(){ resolve("promise 1"); }, 200); }); var promise2 = new RSVP.Promise(function(resolve, reject){ setTimeout(function(){ reject(new Error("promise 2")); }, 100); }); RSVP.race([promise1, promise2]).then(function(result){ // Code here never runs because there are rejected promises! }, function(reason){ // reason.message === "promise2" because promise 2 became rejected before // promise 1 became fulfilled }); ``` @method race @for RSVP @param {Array} promises array of promises to observe @param {String} label optional string for describing the promise returned. Useful for tooling. @return {Promise} a promise that becomes fulfilled with the value the first completed promises is resolved with if the first completed promise was fulfilled, or rejected with the reason that the first completed promise was rejected with. */ function race(promises) { /*jshint validthis:true */ var Promise = this; if (!isArray(promises)) { throw new TypeError('You must pass an array to race.'); } return new Promise(function(resolve, reject) { var results = [], promise; for (var i = 0; i < promises.length; i++) { promise = promises[i]; if (promise && typeof promise.then === 'function') { promise.then(resolve, reject); } else { resolve(promise); } } }); } exports.race = race; },{"./utils":11}],9:[function(_dereq_,module,exports){ "use strict"; /** `RSVP.reject` returns a promise that will become rejected with the passed `reason`. `RSVP.reject` is essentially shorthand for the following: ```javascript var promise = new RSVP.Promise(function(resolve, reject){ reject(new Error('WHOOPS')); }); promise.then(function(value){ // Code here doesn't run because the promise is rejected! }, function(reason){ // reason.message === 'WHOOPS' }); ``` Instead of writing the above, your code now simply becomes the following: ```javascript var promise = RSVP.reject(new Error('WHOOPS')); promise.then(function(value){ // Code here doesn't run because the promise is rejected! }, function(reason){ // reason.message === 'WHOOPS' }); ``` @method reject @for RSVP @param {Any} reason value that the returned promise will be rejected with. @param {String} label optional string for identifying the returned promise. Useful for tooling. @return {Promise} a promise that will become rejected with the given `reason`. */ function reject(reason) { /*jshint validthis:true */ var Promise = this; return new Promise(function (resolve, reject) { reject(reason); }); } exports.reject = reject; },{}],10:[function(_dereq_,module,exports){ "use strict"; function resolve(value) { /*jshint validthis:true */ if (value && typeof value === 'object' && value.constructor === this) { return value; } var Promise = this; return new Promise(function(resolve) { resolve(value); }); } exports.resolve = resolve; },{}],11:[function(_dereq_,module,exports){ "use strict"; function objectOrFunction(x) { return isFunction(x) || (typeof x === "object" && x !== null); } function isFunction(x) { return typeof x === "function"; } function isArray(x) { return Object.prototype.toString.call(x) === "[object Array]"; } // Date.now is not available in browsers < IE9 // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/now#Compatibility var now = Date.now || function() { return new Date().getTime(); }; exports.objectOrFunction = objectOrFunction; exports.isFunction = isFunction; exports.isArray = isArray; exports.now = now; },{}],12:[function(_dereq_,module,exports){ module.exports = _dereq_('./src/createClient'); },{"./src/createClient":21}],13:[function(_dereq_,module,exports){ 'use strict'; function DataTypeValidationError(message){ this.name = 'DataTypeValidationError'; this.message = message || 'Invalid data type'; } DataTypeValidationError.prototype = Object.create(Error.prototype); DataTypeValidationError.prototype.constructor = DataTypeValidationError; exports.DataTypeValidationError = DataTypeValidationError; function NotAnIntegerError(value){ this.name = 'NotAnIntegerError'; this.message = '"' + value + '" is not an integer'; this.value = value; } NotAnIntegerError.prototype = Object.create(DataTypeValidationError.prototype); NotAnIntegerError.prototype.constructor = NotAnIntegerError; exports.NotAnIntegerError = NotAnIntegerError; function NotANumberError(value, actualType){ this.name = 'NotANumberError'; this.message = '"' + value + '" is not a number'; if(actualType) this.message += ' (got a ' + actualType + ' instead)'; this.value = value; } NotANumberError.prototype = Object.create(DataTypeValidationError.prototype); NotANumberError.prototype.constructor = NotANumberError; exports.NotANumberError = NotANumberError; function NumberTooLargeError(value, max){ this.name = 'NumberTooLargeError'; this.message = '"' + value + '" is above the maximum of ' + max.toString(); this.value = value; } NumberTooLargeError.prototype = Object.create(DataTypeValidationError.prototype); NumberTooLargeError.prototype.constructor = NumberTooLargeError; exports.NumberTooLargeError = NumberTooLargeError; function NumberTooSmallError(value, max){ this.name = 'NumberTooSmallError'; this.message = '"' + value + '" is above the maximum of ' + max.toString(); this.value = value; } NumberTooSmallError.prototype = Object.create(DataTypeValidationError.prototype); NumberTooSmallError.prototype.constructor = NumberTooSmallError; exports.NumberTooSmallError = NumberTooSmallError; function NotABooleanError(value, actualType){ this.name = 'NotABooleanError'; this.message = '"' + value + '" is not a boolean'; if(actualType) this.message += ' (got a ' + actualType + ' instead)'; this.value = value; } NotABooleanError.prototype = Object.create(DataTypeValidationError.prototype); NotABooleanError.prototype.constructor = NotABooleanError; exports.NotABooleanError = NotABooleanError; function NotAnArrayError(value, actualType){ this.name = 'NotAnArrayError'; this.message = '"' + value + '" is not an array'; if(actualType) this.message += ' (got a ' + actualType + ' instead)'; this.value = value; } NotAnArrayError.prototype = Object.create(DataTypeValidationError.prototype); NotAnArrayError.prototype.constructor = NotAnArrayError; exports.NotAnArrayError = NotAnArrayError; function DuplicateInSetError(arr, dupes){ this.name = 'DuplicateInSetError'; this.message = 'Duplicates ("' + dupes.join('", "') + '") found in set: ["' + arr.join('", "') + '"'; this.dupes = dupes; this.value = arr; } DuplicateInSetError.prototype = Object.create(DataTypeValidationError.prototype); DuplicateInSetError.prototype.constructor = DuplicateInSetError; exports.DuplicateInSetError = DuplicateInSetError; function NotVoidError(value, actualType){ this.name = 'NotVoidError'; this.message = '"' + value + '" is not null or undefined'; if(actualType) this.message += ' (got a ' + actualType + ' instead)'; this.value = value; } NotVoidError.prototype = Object.create(DataTypeValidationError.prototype); NotVoidError.prototype.constructor = NotVoidError; exports.NotVoidError = NotVoidError; function NotAStringError(value, actualType){ this.name = 'NotAStringError'; this.message = '"' + value + '" is not a string'; if(actualType) this.message += ' (got a ' + actualType + ' instead)'; this.value = value; } NotAStringError.prototype = Object.create(DataTypeValidationError.prototype); NotAStringError.prototype.constructor = NotAStringError; exports.NotAStringError = NotAStringError; function StringNotInEnumError(value, acceptableValues){ this.name = 'StringNotInEnumError'; this.message = '"' + value + '" is not an acceptable value: "' + acceptableValues.join('", "') + '"'; this.value = value; } StringNotInEnumError.prototype = Object.create(DataTypeValidationError.prototype); StringNotInEnumError.prototype.constructor = StringNotInEnumError; exports.StringNotInEnumError = StringNotInEnumError; function ErrorsInArrayElementsError(errors){ this.name = 'ErrorsInArrayElementsError'; this.message = 'Errors in array elements:\n\t' + errors.join(',\n\t'); this.errors = errors; } ErrorsInArrayElementsError.prototype = Object.create(DataTypeValidationError.prototype); ErrorsInArrayElementsError.prototype.constructor = ErrorsInArrayElementsError; exports.ErrorsInArrayElementsError = ErrorsInArrayElementsError; function MissingValueError(){ this.name = 'MissingValueError'; this.message = 'This value is required but missing'; } MissingValueError.prototype = Object.create(DataTypeValidationError.prototype); MissingValueError.prototype.constructor = MissingValueError; exports.MissingValueError = MissingValueError; function ValidationError(specName, spec, error){ this.name = 'ValidationError'; this.specName = specName; this.spec = spec; this.error = error; this.message = specName + ' is invalid: ' + error.message; } ValidationError.prototype = Object.create(DataTypeValidationError.prototype); ValidationError.prototype.constructor = ValidationError; exports.ValidationError = ValidationError; function ValidationErrors(value, specName, spec, errors){ this.name = 'ValidationErrors'; this.value = value; this.specName = specName; this.spec = spec; this.errors = errors || []; this.message = specName + ' is invalid'; if(this.errors.length){ this.message += ':\n\t' + this.errors.map(function(e){ return e.message; }).join('\n\t'); } } ValidationErrors.prototype = Object.create(DataTypeValidationError.prototype); ValidationErrors.prototype.constructor = ValidationErrors; exports.ValidationErrors = ValidationErrors; },{}],14:[function(_dereq_,module,exports){ exports.dataType = _dereq_('./validateDataType'); exports.model = _dereq_('./validateModel'); exports.operation = _dereq_('./validateOperation'); exports.array = _dereq_('./validateArray'); exports.errors = _dereq_('./errorTypes'); var primitives = _dereq_('./validatePrimitiveTypes'); exports.primitive = { integer: primitives.validateInteger, number: primitives.validateNumber, string: primitives.validateString, boolean: primitives.validateBoolean, void: primitives.validateVoid, file: primitives.validateFile }; },{"./errorTypes":13,"./validateArray":15,"./validateDataType":16,"./validateModel":17,"./validateOperation":18,"./validatePrimitiveTypes":19}],15:[function(_dereq_,module,exports){ 'use strict'; var errorTypes = _dereq_('./errorTypes'), validate = _dereq_('./index'); function validateArray(candidate, dataType, models){ if(!Array.isArray(candidate)){ return new errorTypes.NotAnArrayError(candidate, typeof candidate); } var items = dataType.items; if(dataType.uniqueItems){ var dupeCheck = []; var dupes = candidate.filter(function(value){ var signature; if(items.$ref){ signature = JSON.stringify(value); } else { signature = value; } if(dupeCheck.indexOf(signature) !== -1){ return true; } else { dupeCheck.push(signature); return false; } }); if(dupes.length) { return new errorTypes.DuplicateInSetError(candidate, dupes); } } var errors; if(items.$ref){ var model = models[items.$ref]; errors = candidate.filter(function(value){ return validate.model(value, model, models); }); } else { errors = candidate.filter(function(value){ return validate.dataType(value, items, models); }); } if(errors.length){ return new errorTypes.ErrorsInArrayElementsError(errors); } } module.exports = validateArray; },{"./errorTypes":13,"./index":14}],16:[function(_dereq_,module,exports){ 'use strict'; var validate = _dereq_('./index'); function validateDataType(candidate, dataType, models){ models = models || {}; var type = dataType.type || dataType.dataType || dataType.$ref; switch(type){ case 'integer': return validate.primitive.integer(candidate, dataType); case 'number': return validate.primitive.number(candidate, dataType); case 'string': return validate.primitive.string(candidate, dataType); case 'boolean': return validate.primitive.boolean(candidate); case 'array': return validate.array(candidate, dataType, models); case 'void': return validate.primitive.void(candidate); case 'File': return validate.primitive.file(); default: // Assumed to be complex model var model = models[type]; return validate.model(candidate, model, models); } } module.exports = validateDataType; },{"./index":14}],17:[function(_dereq_,module,exports){ 'use strict'; var errorTypes = _dereq_('./errorTypes'), ValidationError = errorTypes.ValidationError, ValidationErrors = errorTypes.ValidationErrors, MissingValueError = errorTypes.MissingValueError, validate = _dereq_('./index'); // http://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-clone-an-object function clone(obj){ if(obj === null || obj === undefined || typeof obj !== 'object') return obj; if(Array.isArray(obj)) return obj.slice(); var temp = {}; for(var key in obj) temp[key] = clone(obj[key]); return temp; } function addInhertiedProperties(model, modelId, models){ var parent; Object.keys(models).some(function(modelName){ var potentialParent = models[modelName]; if (!potentialParent.subTypes) return; if(potentialParent.subTypes.indexOf(modelId) !== -1){ parent = potentialParent; return true; } }); if(!parent) return; for(var propertyName in parent.properties){ model.properties[propertyName] = parent.properties[propertyName]; } if(parent.required) model.required = model.required.concat(parent.required); addInhertiedProperties(model, parent.id, models); } function validateModel(candidate, model, models){ if(candidate === null || typeof candidate !== 'object'){ return new ValidationErrors(candidate, model); } models = models || {}; model = clone(model); if(!model.required) model.required = []; addInhertiedProperties(model, model.id, models); var errors = []; model.required.forEach(function(propertyName){ if (candidate[propertyName] !== undefined) return; var property = model.properties[propertyName]; var error = new MissingValueError(); errors.push(new ValidationError(propertyName, property, error)); }); Object.keys(candidate).forEach(function(propertyName){ var property = model.properties[propertyName]; if(property === undefined) return; var error = validate.dataType(candidate[propertyName], property, models); if(error){ errors.push(new ValidationError(propertyName, property, error)); } }); if(errors.length){ return new ValidationErrors(candidate, model.id, model, errors); } } module.exports = validateModel; },{"./errorTypes":13,"./index":14}],18:[function(_dereq_,module,exports){ 'use strict'; var errorTypes = _dereq_('./errorTypes'), ValidationError = errorTypes.ValidationError, ValidationErrors = errorTypes.ValidationErrors, MissingValueError = errorTypes.MissingValueError, validate = _dereq_('./index'); function validateOperation(candidate, operation, models){ var errors = []; var presentParams = operation.parameters.filter(function(param){ if (candidate[param.name] !== undefined) return true; if (param.required) { var error = new MissingValueError(); errors.push(new ValidationError(param.name, param, error)); } return false; }); presentParams.forEach(function(param){ var error = validate.dataType(candidate[param.name], param, models); if(error){ errors.push(new ValidationError(param.name, param, error)); } }); if(errors.length){ return new ValidationErrors(candidate, operation.nickname, operation, errors); } } module.exports = validateOperation; },{"./errorTypes":13,"./index":14}],19:[function(_dereq_,module,exports){ 'use strict'; var errorTypes = _dereq_('./errorTypes'); function validateInteger(candidate, dataType){ var error = validateNumber(candidate, dataType); if(error) return error; if(candidate % 1){ return new errorTypes.NotAnIntegerError(candidate); } } exports.validateInteger = validateInteger; function validateNumber(candidate, dataType){ if(!(typeof candidate === 'number' || candidate instanceof Number) || isNaN(candidate)){ return new errorTypes.NotANumberError(candidate, typeof candidate); } if((dataType.minimum !== undefined) && candidate < parseInt(dataType.minimum, 10)){ return new errorTypes.NumberTooSmallError(candidate, dataType.minimum); } if((dataType.maximum !== undefined) && candidate > parseInt(dataType.maximum, 10)){ return new errorTypes.NumberTooLargeError(candidate, dataType.maximum); } } exports.validateNumber = validateNumber; function validateBoolean(candidate){ if(!(typeof candidate === 'boolean' || candidate instanceof Boolean)){ return new errorTypes.NotABooleanError(candidate, typeof candidate); } } exports.validateBoolean = validateBoolean; function validateVoid(candidate){ if(candidate != null){ return new errorTypes.NotVoidError(candidate, typeof candidate); } } exports.validateVoid = validateVoid; function validateFile(){ // Not sure how to check this, since anything could qualify as 'File'. } exports.validateFile = validateFile; function validateString(candidate, dataType){ if(typeof candidate !== 'string' && !(candidate instanceof String)){ return new errorTypes.NotAStringError(candidate, typeof candidate); } if('enum' in dataType){ if(dataType.enum.indexOf(candidate) === -1) { return new errorTypes.StringNotInEnumError(candidate, dataType.enum); } } } exports.validateString = validateString; },{"./errorTypes":13}],20:[function(_dereq_,module,exports){ 'use strict'; var MissingAuthorizationError = _dereq_('./errorTypes').MissingAuthorizationError; module.exports = function applyAuthData(operation, authData, request){ var authMap = operation.authorizations; if(!authMap) authMap = operation.apiObject.apiDeclaration.authorizations; if(!authMap) return; var authNames = Object.keys(authMap).filter(function(authName){ // Currently unable to handle oauth2 return authMap[authName].type !== 'oauth2'; }); if(authNames.length === 0) return; if(authNames.length === 1){ var authName = authNames[0]; var auth = authMap[authName]; if(!authData) throw new MissingAuthorizationError(authName, auth); // Unpack nested authData for single auth ops: { apiKey: '123' } -> '123' if(authData[authName]) authData = authData[authName]; if(auth.type === 'apiKey'){ applyApiKey(auth, authName, authData, request); } else if(auth.type === 'basicAuth') { applyBasicAuth(auth, authName, authData.username, authData.password, request); } } else { var hasAuth = authNames.some(function(authName){ var auth = authMap[authName]; var data = authData[authName]; if(!data) return false; if(auth.type === 'apiKey'){ applyApiKey(auth, authName, data, request); } else if(auth.type === 'basicAuth'){ applyBasicAuth(auth, authName, data.username, data.password, request); } return true; }); if(!hasAuth){ throw new MissingAuthorizationError(authNames.join(', '), authMap); } } }; function applyApiKey(auth, authName, apiKey, request){ if(!apiKey) throw new MissingAuthorizationError(authName, auth); if(auth.passAs === 'header'){ request.headers[auth.keyname] = apiKey; } else if(auth.passAs === 'query'){ var url = request.url; var queryParam = auth.keyname + '=' + encodeURIComponent(apiKey); if(url.indexOf('?') === -1){ url += '?' + queryParam; } else { url = url.replace('?', '?' + queryParam + '&'); } request.url = url; } } function applyBasicAuth(auth, authName, username, password, request){ if(!username || !password) throw new MissingAuthorizationError(authName, auth); var url = request.url; // Only add basic auth once if(url.indexOf('@') === -1){ url = url.replace('://', '://' + username + ':' + password + '@'); } request.url = url; } },{"./errorTypes":23}],21:[function(_dereq_,module,exports){ 'use strict'; var createOperationHandler = _dereq_('./createOperationHandler'); function createClient(schema, requestHandler){ var api = {}, apiAuthData, authMethodName = 'auth'; schema = processSchema(schema); // If the 'auth' key is used for any resource or operation, we'll use // 'authorization' instead for the auth methods var authIsInUse = schema.apis.some(function(resourceObject){ return resourceObject.apiDeclaration.apis.some(function(apiObject){ var resourceApiName = getApiName(apiObject.apiDeclaration.resourcePath || apiObject.path); if(resourceApiName === 'auth') return true; return apiObject.operations.some(function(operation){ return operation.nickname === 'auth'; }); }); }); if(authIsInUse) authMethodName = 'authorization'; api[authMethodName] = function(){ apiAuthData = processApiAuthArgs(arguments); }; schema.apis.forEach(function(resourceObject){ var resourceName, resourceApi, resourceAuthData; if(resourceObject.apiDeclaration.resourcePath){ resourceName = getApiName(resourceObject.apiDeclaration.resourcePath); resourceApi = api[resourceName] = {}; resourceApi[authMethodName] = function(){ resourceAuthData = processApiAuthArgs(arguments); }; } resourceObject.apiDeclaration.apis.forEach(function(apiObject){ var apiObjectName = resourceName, apiObjectApi = resourceApi, apiObjectAuthData; if(!apiObjectName){ apiObjectName = getApiName(apiObject.path); apiObjectApi = api[apiObjectName] = {}; apiObjectApi[authMethodName] = function(){ apiObjectAuthData = processApiAuthArgs(arguments); }; } apiObject.operations.forEach(function(operation){ var operationHandlerName = operation.nickname, operationAuthData, operationHandler; function getAuthData(){ return operationAuthData || apiObjectAuthData || resourceAuthData || apiAuthData; } operationHandler = createOperationHandler(operation, getAuthData, requestHandler); operationHandler[authMethodName] = function(){ operationAuthData = processApiAuthArgs(arguments); }; apiObjectApi[operationHandlerName] = operationHandler; }); }); }); return api; } module.exports = createClient; function processApiAuthArgs(args){ // for basic auth, allow calls with two args (username, password) if(typeof args[0] === 'string' && typeof args[1] === 'string') { return { username: args[0], password: args[1] }; } else { return args[0]; } } // Helpper method which assings back pointer to object parents and returns // the api objects within the given schema. function processSchema(schema){ schema.apis.forEach(function(resourceObject){ resourceObject.resourceListing = schema; resourceObject.apiDeclaration.apis.forEach(function(apiObject){ apiObject.resourceObject = resourceObject; apiObject.apiDeclaration = resourceObject.apiDeclaration; apiObject.operations.forEach(function(operation){ operation.apiObject = apiObject; operation.parameters.forEach(function(parameter){ parameter.operation = operation; }); }); }); }); return schema; } // Takes a path and returns a JavaScript-friendly variable name function getApiName(name){ // String non-word characters name = name.replace(/\W/g, '/'); // Turn paths which look/like/this to lookLikeThis name = name.replace(/(\w)\/(\w)/g, function(match, p1, p2){ return p1 + p2.toUpperCase(); }); name = name.replace(/\//g, ''); return name; } },{"./createOperationHandler":22}],22:[function(_dereq_,module,exports){ 'use strict'; var getRequestHeaders = _dereq_('./getRequestHeaders'), getRequestUrl = _dereq_('./getRequestUrl'), getRequestBody = _dereq_('./getRequestBody'), applyAuthData = _dereq_('./applyAuthData'), errorTypes = _dereq_('./errorTypes'), swaggerValidate = _dereq_('swagger-validate'); var allErrorTypes = {}; Object.keys(swaggerValidate.errors).forEach(function(errorName){ allErrorTypes[errorName] = swaggerValidate.errors[errorName]; }); Object.keys(errorTypes).forEach(function(errorName){ allErrorTypes[errorName] = errorTypes[errorName]; }); function createOperationHandler(operation, getAuthData, requestHandler){ function Request(data, options){ this.method = operation.method; this.operation = operation; this.errorTypes = allErrorTypes; this.data = data; this.options = options; } var operationHandler = function(data, options){ var error, request; options = options || {}; if(data == null) data = {}; // if a function is passed in as options, assume it's a callback function // for convenience if(typeof options === 'function'){ options.callback = options; } try{ data = prune(data); data = singleParamConvenienceProcessor(operation, data); data = removeUnknownParams(operation, data); error = swaggerValidate.operation(data, operation, operation.apiObject.apiDeclaration.models); request = new Request(data, options); // If we know there is an error, don't attempt to craft the request params. // The request param generators assume valid data to work properly. if(!error){ request.url = getRequestUrl(operation, data); request.headers = getRequestHeaders(operation, data, options); request.body = getRequestBody(operation, data, request.headers); applyAuthData(operation, getAuthData(), request); } } catch(e){ error = e; } return requestHandler(error, request); }; // Useful for instanceof checks operationHandler.Request = Request; operationHandler.errorTypes = allErrorTypes; // Useful for reflection operationHandler.operation = operation; // Can be used to preemptively validate without action operationHandler.validate = function(data){ return swaggerValidate.operation(data, operation, operation.apiObject.apiDeclaration.models); }; return operationHandler; } module.exports = createOperationHandler; function noop(){} createOperationHandler.logger = { debug: noop, info: noop, warn: noop, error: noop }; // Stringify and parse the data to clean up undefined, and non-scalar properties function prune(data){ return JSON.parse(JSON.stringify(data)); } // Enables data to be passed directly for single param operations. function singleParamConvenienceProcessor(operation, data){ // If there are more than one params, bail var requiredParams = operation.parameters.filter(function(param){ return param.required; }); // If there are more than one required params, or if there is no required param // and there are many optional params, bail if(requiredParams.length > 1) return data; if(requiredParams.length !== 1 && operation.parameters.length !== 1) return data; var param = requiredParams[0] || operation.parameters[0]; // If the param is already defined explicitly, bail if(typeof data === 'object' && data[param.name] !== undefined) return data; var models = operation.apiObject.apiDeclaration.models; // If the data passed is is not valid for the param data type, bail var error; try { error = swaggerValidate.dataType(data, param, models); } catch(e){ return data; } // If the data passed is a valid param data type, bail if(!error){ var wrapper = {}; wrapper[param.name] = data; return wrapper; } else { return data; } } function removeUnknownParams(operation, data){ if(!data || typeof data !== 'object') return data; var paramNames = {}; operation.parameters.forEach(function(param){ paramNames[param.name] = true; }); var unknownKeys = Object.keys(data).filter(function(key){ return !(key in paramNames); }); createOperationHandler.logger.warn('Unknown parameters removed from request:', unknownKeys.join(', ')); unknownKeys.forEach(function(key){ delete data[key]; }); return data; } },{"./applyAuthData":20,"./errorTypes":23,"./getRequestBody":24,"./getRequestHeaders":25,"./getRequestUrl":26,"swagger-validate":14}],23:[function(_dereq_,module,exports){ 'use strict'; function InvalidRequestError(message){ this.name = 'InvalidRequestError'; this.message = message || 'Invalid request'; } InvalidRequestError.prototype = Object.create(Error.prototype); InvalidRequestError.prototype.constructor = InvalidRequestError; exports.InvalidRequestError = InvalidRequestError; function MissingAuthorizationError(authName, auth){ this.name = 'MissingAuthorizationError'; this.message = 'No data found for authorization: ' + authName; this.authorization = auth; } MissingAuthorizationError.prototype = Object.create(InvalidRequestError.prototype); MissingAuthorizationError.prototype.constructor = MissingAuthorizationError; exports.MissingAuthorizationError = MissingAuthorizationError; function MissingPathParamsError(pathParams){ this.name = 'MissingPathParamsError'; this.message = 'Missing the following required path parameters: ' + pathParams.join(''); } MissingPathParamsError.prototype = Object.create(InvalidRequestError.prototype); MissingPathParamsError.prototype.constructor = MissingPathParamsError; exports.MissingPathParamsError = MissingPathParamsError; function ContentTypeNotSupportedError(contentType, operation){ var apiDeclaration = operation.apiObject.apiDeclaration; var consumes = operation.consumes || apiDeclaration.consumes || []; this.name = 'ContentTypeNotSupportedError'; this.message = 'Operation [' + operation.nickname + '] does not accept ' + contentType + '. It supports: ' + consumes.join(', '); } ContentTypeNotSupportedError.prototype = Object.create(InvalidRequestError.prototype); ContentTypeNotSupportedError.prototype.constructor = ContentTypeNotSupportedError; exports.ContentTypeNotSupportedError = ContentTypeNotSupportedError; function AcceptsNotSupportedError(accepts, operation){ var apiDeclaration = operation.apiObject.apiDeclaration; var produces = operation.produces || apiDeclaration.produces || []; this.name = 'AcceptsNotSupportedError'; this.message = 'Operation [' + operation.nickname + '] does not produce ' + accepts + '. It supports: ' + produces.join(', '); } AcceptsNotSupportedError.prototype = Object.create(InvalidRequestError.prototype); AcceptsNotSupportedError.prototype.constructor = AcceptsNotSupportedError; exports.AcceptsNotSupportedError = AcceptsNotSupportedError; function OperationValidationError(operation, errors){ this.name = 'OperationValidationError'; this.message = operation.nickname + ' failed validation: \n\t' + errors.join('\n\t'); } OperationValidationError.prototype = Object.create(InvalidRequestError.prototype); OperationValidationError.prototype.constructor = OperationValidationError; exports.OperationValidationError = OperationValidationError; function ParameterValidationError(parameter, errors){ this.name = 'ParameterValidationError'; this.message = parameter.name + ' failed validation: \n\t' + errors.join('\n\t'); } ParameterValidationError.prototype = Object.create(InvalidRequestError.prototype); ParameterValidationError.prototype.constructor = ParameterValidationError; exports.ParameterValidationError = ParameterValidationError; function DataTypeValidationError(message){ this.name = 'DataTypeValidationError'; this.message = message || 'Invalid data type'; } DataTypeValidationError.prototype = Object.create(Error.prototype); DataTypeValidationError.prototype.constructor = DataTypeValidationError; exports.DataTypeValidationError = DataTypeValidationError; },{}],24:[function(_dereq_,module,exports){ 'use strict'; module.exports = function getRequestBody(operation, data, headers){ var body = operation.parameters.filter(function(param){ return param.paramType === 'body' && data[param.name] != null; }).map(function(param){ return data[param.name]; })[0]; if(!(headers && headers['Content-Type'])) return body; var contentType = headers['Content-Type']; var presentFormParams = operation.parameters.filter(function(param){ return param.paramType === 'form' && data[param.name] != null; }); if(contentType.indexOf('application/x-www-form-urlencoded') !== -1){ body = presentFormParams.map(function(param){ var key = param.name, value = data[key]; return encodeURIComponent(key) + '=' + encodeURIComponent(value); }).join('&'); } else if(contentType.indexOf('multipart/form-data') !== -1){ var randomness = Math.random().toString(16).substr(2); var boundary = 'SwaggerBoundary' + randomness; body = presentFormParams.map(function(param){ var key = param.name, value = data[key], result = '--' + boundary; result += '\nContent-Disposition: form-data; name="' + key + '"'; if(value.contentType){ if(value.name){ result += '; filename="' + value.name + '"'; } result += '\nContent-Type: ' + value.contentType; } if(value.contentTransferEncoding){ result += '\nContent-Transfer-Encoding: ' + value.contentTransferEncoding; } if(value.body){ result += '\n\n' + value.body; } else { result += '\n\n' + value; } return result; }).join('\n'); body += '\n--' + boundary + '--\n'; headers['Content-Type'] = contentType.replace( 'multipart/form-data', 'multipart/form-data; boundary=' + boundary ); } else if(contentType.indexOf('application/json') !== -1){ if(typeof body !== 'string'){ body = JSON.stringify(body); } } return body; }; },{}],25:[function(_dereq_,module,exports){ 'use strict'; var errorTypes = _dereq_('./errorTypes'), ContentTypeNotSupportedError = errorTypes.ContentTypeNotSupportedError, AcceptsNotSupportedError = errorTypes.AcceptsNotSupportedError; var DEFAULT_ACCEPT = 'application/json'; module.exports = function getRequestHeaders(operation, data, options){ data = data || {}; options = options || {}; var headers = {}; operation.parameters.forEach(function(param){ if(param.paramType === 'header' && data[param.name] != null){ headers[param.name] = data[param.name]; } }); // Passed headers if(options.headers){ Object.keys(options.headers).forEach(function(key){ headers[key] = options.headers[key]; }); } // Content-Type var contentType = options.contentType || getContentType(operation, data, options); if(contentType) { if(hasAccept(operation, contentType)){ headers['Content-Type'] = contentType; } else { throw new ContentTypeNotSupportedError(contentType, operation); } } // Accept var accept = options.accept || DEFAULT_ACCEPT; if(accept){ if(hasContentType(operation, accept)){ headers.Accept = accept; } else { throw new AcceptsNotSupportedError(accept, operation); } } return headers; }; function getContentType(operation, data){ var hasBody = operation.parameters.some(function(param){ return param.paramType === 'body' && data[param.name] !== undefined; }); if (hasBody){ return 'application/json'; } else { var hasFormParams = operation.parameters.some(function(param){ return param.paramType === 'form' && data[param.name] !== undefined; }); var hasFileParam = hasFormParams && operation.parameters.some(function(param){ return param.type === 'File' && data[param.name] !== undefined; }); if(hasFileParam) return 'multipart/form-data'; else if(hasFormParams) return 'application/x-www-form-urlencoded'; } } // Accepts is an optional field in the spec, but must be enforced when present function hasAccept(operation, contentType){ var apiDeclaration = operation.apiObject.apiDeclaration; var accepts = operation.consumes || apiDeclaration.consumes; if(accepts && accepts.length){ return accepts.indexOf(contentType) !== -1; } else { return true; } } exports.hasAccept = hasAccept; // Content-Type (produces) is an optional field in the spec, but must be enforced when present function hasContentType(operation, contentType){ var apiDeclaration = operation.apiObject.apiDeclaration, contentTypes = operation.produces || apiDeclaration.produces; if(contentTypes && contentTypes.length){ return contentTypes.indexOf(contentType) !== -1; } else { return true; } } exports.hasContentType = hasContentType; },{"./errorTypes":23}],26:[function(_dereq_,module,exports){ 'use strict'; var errorTypes = _dereq_('./errorTypes'), MissingPathParamsError = errorTypes.MissingPathParamsError; module.exports = function getRequestUrl(operation, data){ var url = getUrlTemplate(operation); url = applyPathParams(url, operation, data); if(!data) return url; var queryParams = operation.parameters.filter(function(param){ return param.paramType === 'query' && data[param.name] !== undefined; }).map(function(param){ var key = param.name; return encodeURIComponent(key) + '=' + encodeURIComponent(data[key]); }).join('&'); if(queryParams) url += '?' + queryParams; return url; }; function applyPathParams(url, operation, data){ var pathParams = operation.parameters.filter(function(param){ return param.paramType === 'path'; }); var missingParams = pathParams.filter(function(param){ return data[param.name] === undefined; }); if(missingParams.length){ throw new MissingPathParamsError(missingParams.map(function(param){ return param.name; })); } pathParams.forEach(function(param){ var key = param.name; var exp = new RegExp('{' + key + '[^}]*}', 'gi'); var value = data[key].toString(); delete data[key]; value = value.split('/').map(encodeURIComponent).join('/'); url = url.replace(exp, value); }); return url; } function getUrlTemplate(operation){ var apiObject = operation.apiObject; var basePath = apiObject.apiDeclaration.basePath; var path = apiObject.path.replace('{format}', 'json'); return basePath + path; } },{"./errorTypes":23}],27:[function(_dereq_,module,exports){ 'use strict'; // Promise polyfill var Promise = _dereq_('es6-promise').Promise; var clientGenerator = _dereq_('swagger-client-generator'); module.exports = function(schema){ return clientGenerator(schema, requestHandler); }; // For mocking during unit testing if(typeof XMLHttpRequest !== 'undefined'){ module.exports.XMLHttpRequest = window.XMLHttpRequest; } function requestHandler(error, request){ var XMLHttpRequest = module.exports.XMLHttpRequest; return new Promise(function(resolve, reject){ if(error) return reject(error); var method = request.method; var url = request.url; var body = request.body; var headers = request.headers; var options = request.options; var async = ('async' in options)? options.async : true; var xhr = new XMLHttpRequest(); xhr.open(method, url, async); if(headers){ Object.keys(headers).forEach(function(header){ xhr.setRequestHeader(header, headers[header]); }); } if(options.withCredentials) xhr.withCredentials = options.withCredentials; if(options.timeout) xhr.timeout = options.timeout; if(options.onabort) xhr.onabort = options.onabort; if(options.onerror) xhr.onerror = options.onerror; if(options.onload) xhr.onload = options.onload; if(options.ontimeout) xhr.ontimeout = options.ontimeout; if(options.onprogress) xhr.onprogress = options.onprogress; xhr.onloadend = function(){ var data = this.response; var contentType = this.getResponseHeader('Content-Type'); if(contentType && contentType.indexOf('application/json') !== -1){ try { data = JSON.parse(data); } catch(error){ reject({ error: error, status: this.status, data: data }); } } if(this.status < 200 || this.status >= 300){ reject({ error: error, status: this.status, data: data }); } else { resolve(data); } if(options.onloadend) options.onloadend.call(this); }; xhr.send(body); }); } },{"es6-promise":2,"swagger-client-generator":12}]},{},[27]) //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvYm9pbGVycGxhdGUtZ3VscC9ub2RlX21vZHVsZXMvYnJvd3NlcmlmeS9ub2RlX21vZHVsZXMvYnJvd3Nlci1wYWNrL19wcmVsdWRlLmpzIiwiL1VzZXJzL296YW4vY29kZS9zd2FnZ2VyLWFqYXgtY2xpZW50L25vZGVfbW9kdWxlcy9ib2lsZXJwbGF0ZS1ndWxwL25vZGVfbW9kdWxlcy9icm93c2VyaWZ5L25vZGVfbW9kdWxlcy9wcm9jZXNzL2Jyb3dzZXIuanMiLCIvVXNlcnMvb3phbi9jb2RlL3N3YWdnZXItYWpheC1jbGllbnQvbm9kZV9tb2R1bGVzL2VzNi1wcm9taXNlL2Rpc3QvY29tbW9uanMvbWFpbi5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvZXM2LXByb21pc2UvZGlzdC9jb21tb25qcy9wcm9taXNlL2FsbC5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvZXM2LXByb21pc2UvZGlzdC9jb21tb25qcy9wcm9taXNlL2FzYXAuanMiLCIvVXNlcnMvb3phbi9jb2RlL3N3YWdnZXItYWpheC1jbGllbnQvbm9kZV9tb2R1bGVzL2VzNi1wcm9taXNlL2Rpc3QvY29tbW9uanMvcHJvbWlzZS9jb25maWcuanMiLCIvVXNlcnMvb3phbi9jb2RlL3N3YWdnZXItYWpheC1jbGllbnQvbm9kZV9tb2R1bGVzL2VzNi1wcm9taXNlL2Rpc3QvY29tbW9uanMvcHJvbWlzZS9wb2x5ZmlsbC5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvZXM2LXByb21pc2UvZGlzdC9jb21tb25qcy9wcm9taXNlL3Byb21pc2UuanMiLCIvVXNlcnMvb3phbi9jb2RlL3N3YWdnZXItYWpheC1jbGllbnQvbm9kZV9tb2R1bGVzL2VzNi1wcm9taXNlL2Rpc3QvY29tbW9uanMvcHJvbWlzZS9yYWNlLmpzIiwiL1VzZXJzL296YW4vY29kZS9zd2FnZ2VyLWFqYXgtY2xpZW50L25vZGVfbW9kdWxlcy9lczYtcHJvbWlzZS9kaXN0L2NvbW1vbmpzL3Byb21pc2UvcmVqZWN0LmpzIiwiL1VzZXJzL296YW4vY29kZS9zd2FnZ2VyLWFqYXgtY2xpZW50L25vZGVfbW9kdWxlcy9lczYtcHJvbWlzZS9kaXN0L2NvbW1vbmpzL3Byb21pc2UvcmVzb2x2ZS5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvZXM2LXByb21pc2UvZGlzdC9jb21tb25qcy9wcm9taXNlL3V0aWxzLmpzIiwiL1VzZXJzL296YW4vY29kZS9zd2FnZ2VyLWFqYXgtY2xpZW50L25vZGVfbW9kdWxlcy9zd2FnZ2VyLWNsaWVudC1nZW5lcmF0b3IvaW5kZXguanMiLCIvVXNlcnMvb3phbi9jb2RlL3N3YWdnZXItYWpheC1jbGllbnQvbm9kZV9tb2R1bGVzL3N3YWdnZXItY2xpZW50LWdlbmVyYXRvci9ub2RlX21vZHVsZXMvc3dhZ2dlci12YWxpZGF0ZS9zcmMvZXJyb3JUeXBlcy5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvc3dhZ2dlci1jbGllbnQtZ2VuZXJhdG9yL25vZGVfbW9kdWxlcy9zd2FnZ2VyLXZhbGlkYXRlL3NyYy9pbmRleC5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvc3dhZ2dlci1jbGllbnQtZ2VuZXJhdG9yL25vZGVfbW9kdWxlcy9zd2FnZ2VyLXZhbGlkYXRlL3NyYy92YWxpZGF0ZUFycmF5LmpzIiwiL1VzZXJzL296YW4vY29kZS9zd2FnZ2VyLWFqYXgtY2xpZW50L25vZGVfbW9kdWxlcy9zd2FnZ2VyLWNsaWVudC1nZW5lcmF0b3Ivbm9kZV9tb2R1bGVzL3N3YWdnZXItdmFsaWRhdGUvc3JjL3ZhbGlkYXRlRGF0YVR5cGUuanMiLCIvVXNlcnMvb3phbi9jb2RlL3N3YWdnZXItYWpheC1jbGllbnQvbm9kZV9tb2R1bGVzL3N3YWdnZXItY2xpZW50LWdlbmVyYXRvci9ub2RlX21vZHVsZXMvc3dhZ2dlci12YWxpZGF0ZS9zcmMvdmFsaWRhdGVNb2RlbC5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvc3dhZ2dlci1jbGllbnQtZ2VuZXJhdG9yL25vZGVfbW9kdWxlcy9zd2FnZ2VyLXZhbGlkYXRlL3NyYy92YWxpZGF0ZU9wZXJhdGlvbi5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvc3dhZ2dlci1jbGllbnQtZ2VuZXJhdG9yL25vZGVfbW9kdWxlcy9zd2FnZ2VyLXZhbGlkYXRlL3NyYy92YWxpZGF0ZVByaW1pdGl2ZVR5cGVzLmpzIiwiL1VzZXJzL296YW4vY29kZS9zd2FnZ2VyLWFqYXgtY2xpZW50L25vZGVfbW9kdWxlcy9zd2FnZ2VyLWNsaWVudC1nZW5lcmF0b3Ivc3JjL2FwcGx5QXV0aERhdGEuanMiLCIvVXNlcnMvb3phbi9jb2RlL3N3YWdnZXItYWpheC1jbGllbnQvbm9kZV9tb2R1bGVzL3N3YWdnZXItY2xpZW50LWdlbmVyYXRvci9zcmMvY3JlYXRlQ2xpZW50LmpzIiwiL1VzZXJzL296YW4vY29kZS9zd2FnZ2VyLWFqYXgtY2xpZW50L25vZGVfbW9kdWxlcy9zd2FnZ2VyLWNsaWVudC1nZW5lcmF0b3Ivc3JjL2NyZWF0ZU9wZXJhdGlvbkhhbmRsZXIuanMiLCIvVXNlcnMvb3phbi9jb2RlL3N3YWdnZXItYWpheC1jbGllbnQvbm9kZV9tb2R1bGVzL3N3YWdnZXItY2xpZW50LWdlbmVyYXRvci9zcmMvZXJyb3JUeXBlcy5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvc3dhZ2dlci1jbGllbnQtZ2VuZXJhdG9yL3NyYy9nZXRSZXF1ZXN0Qm9keS5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvc3dhZ2dlci1jbGllbnQtZ2VuZXJhdG9yL3NyYy9nZXRSZXF1ZXN0SGVhZGVycy5qcyIsIi9Vc2Vycy9vemFuL2NvZGUvc3dhZ2dlci1hamF4LWNsaWVudC9ub2RlX21vZHVsZXMvc3dhZ2dlci1jbGllbnQtZ2VuZXJhdG9yL3NyYy9nZXRSZXF1ZXN0VXJsLmpzIiwiL1VzZXJzL296YW4vY29kZS9zd2FnZ2VyLWFqYXgtY2xpZW50L3NyYy9jbGllbnQuanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3ZDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4RkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM5Q0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3JCQTs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNmQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNuREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDOUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pGQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9IQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDM0pBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeEZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDbkVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzlEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJmaWxlIjoiZ2VuZXJhdGVkLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXNDb250ZW50IjpbIihmdW5jdGlvbiBlKHQsbixyKXtmdW5jdGlvbiBzKG8sdSl7aWYoIW5bb10pe2lmKCF0W29dKXt2YXIgYT10eXBlb2YgcmVxdWlyZT09XCJmdW5jdGlvblwiJiZyZXF1aXJlO2lmKCF1JiZhKXJldHVybiBhKG8sITApO2lmKGkpcmV0dXJuIGkobywhMCk7dGhyb3cgbmV3IEVycm9yKFwiQ2Fubm90IGZpbmQgbW9kdWxlICdcIitvK1wiJ1wiKX12YXIgZj1uW29dPXtleHBvcnRzOnt9fTt0W29dWzBdLmNhbGwoZi5leHBvcnRzLGZ1bmN0aW9uKGUpe3ZhciBuPXRbb11bMV1bZV07cmV0dXJuIHMobj9uOmUpfSxmLGYuZXhwb3J0cyxlLHQsbixyKX1yZXR1cm4gbltvXS5leHBvcnRzfXZhciBpPXR5cGVvZiByZXF1aXJlPT1cImZ1bmN0aW9uXCImJnJlcXVpcmU7Zm9yKHZhciBvPTA7bzxyLmxlbmd0aDtvKyspcyhyW29dKTtyZXR1cm4gc30pIiwiLy8gc2hpbSBmb3IgdXNpbmcgcHJvY2VzcyBpbiBicm93c2VyXG5cbnZhciBwcm9jZXNzID0gbW9kdWxlLmV4cG9ydHMgPSB7fTtcblxucHJvY2Vzcy5uZXh0VGljayA9IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGNhblNldEltbWVkaWF0ZSA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnNldEltbWVkaWF0ZTtcbiAgICB2YXIgY2FuUG9zdCA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnXG4gICAgJiYgd2luZG93LnBvc3RNZXNzYWdlICYmIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyXG4gICAgO1xuXG4gICAgaWYgKGNhblNldEltbWVkaWF0ZSkge1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gKGYpIHsgcmV0dXJuIHdpbmRvdy5zZXRJbW1lZGlhdGUoZikgfTtcbiAgICB9XG5cbiAgICBpZiAoY2FuUG9zdCkge1xuICAgICAgICB2YXIgcXVldWUgPSBbXTtcbiAgICAgICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21lc3NhZ2UnLCBmdW5jdGlvbiAoZXYpIHtcbiAgICAgICAgICAgIHZhciBzb3VyY2UgPSBldi5zb3VyY2U7XG4gICAgICAgICAgICBpZiAoKHNvdXJjZSA9PT0gd2luZG93IHx8IHNvdXJjZSA9PT0gbnVsbCkgJiYgZXYuZGF0YSA9PT0gJ3Byb2Nlc3MtdGljaycpIHtcbiAgICAgICAgICAgICAgICBldi5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgICAgICAgICBpZiAocXVldWUubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZm4gPSBxdWV1ZS5zaGlmdCgpO1xuICAgICAgICAgICAgICAgICAgICBmbigpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSwgdHJ1ZSk7XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIG5leHRUaWNrKGZuKSB7XG4gICAgICAgICAgICBxdWV1ZS5wdXNoKGZuKTtcbiAgICAgICAgICAgIHdpbmRvdy5wb3N0TWVzc2FnZSgncHJvY2Vzcy10aWNrJywgJyonKTtcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICByZXR1cm4gZnVuY3Rpb24gbmV4dFRpY2soZm4pIHtcbiAgICAgICAgc2V0VGltZW91dChmbiwgMCk7XG4gICAgfTtcbn0pKCk7XG5cbnByb2Nlc3MudGl0bGUgPSAnYnJvd3Nlcic7XG5wcm9jZXNzLmJyb3dzZXIgPSB0cnVlO1xucHJvY2Vzcy5lbnYgPSB7fTtcbnByb2Nlc3MuYXJndiA9IFtdO1xuXG5mdW5jdGlvbiBub29wKCkge31cblxucHJvY2Vzcy5vbiA9IG5vb3A7XG5wcm9jZXNzLmFkZExpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3Mub25jZSA9IG5vb3A7XG5wcm9jZXNzLm9mZiA9IG5vb3A7XG5wcm9jZXNzLnJlbW92ZUxpc3RlbmVyID0gbm9vcDtcbnByb2Nlc3MucmVtb3ZlQWxsTGlzdGVuZXJzID0gbm9vcDtcbnByb2Nlc3MuZW1pdCA9IG5vb3A7XG5cbnByb2Nlc3MuYmluZGluZyA9IGZ1bmN0aW9uIChuYW1lKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmJpbmRpbmcgaXMgbm90IHN1cHBvcnRlZCcpO1xufVxuXG4vLyBUT0RPKHNodHlsbWFuKVxucHJvY2Vzcy5jd2QgPSBmdW5jdGlvbiAoKSB7IHJldHVybiAnLycgfTtcbnByb2Nlc3MuY2hkaXIgPSBmdW5jdGlvbiAoZGlyKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKCdwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbn07XG4iLCJcInVzZSBzdHJpY3RcIjtcbnZhciBQcm9taXNlID0gcmVxdWlyZShcIi4vcHJvbWlzZS9wcm9taXNlXCIpLlByb21pc2U7XG52YXIgcG9seWZpbGwgPSByZXF1aXJlKFwiLi9wcm9taXNlL3BvbHlmaWxsXCIpLnBvbHlmaWxsO1xuZXhwb3J0cy5Qcm9taXNlID0gUHJvbWlzZTtcbmV4cG9ydHMucG9seWZpbGwgPSBwb2x5ZmlsbDsiLCJcInVzZSBzdHJpY3RcIjtcbi8qIGdsb2JhbCB0b1N0cmluZyAqL1xuXG52YXIgaXNBcnJheSA9IHJlcXVpcmUoXCIuL3V0aWxzXCIpLmlzQXJyYXk7XG52YXIgaXNGdW5jdGlvbiA9IHJlcXVpcmUoXCIuL3V0aWxzXCIpLmlzRnVuY3Rpb247XG5cbi8qKlxuICBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCB3aGVuIGFsbCB0aGUgZ2l2ZW4gcHJvbWlzZXMgaGF2ZSBiZWVuXG4gIGZ1bGZpbGxlZCwgb3IgcmVqZWN0ZWQgaWYgYW55IG9mIHRoZW0gYmVjb21lIHJlamVjdGVkLiBUaGUgcmV0dXJuIHByb21pc2VcbiAgaXMgZnVsZmlsbGVkIHdpdGggYW4gYXJyYXkgdGhhdCBnaXZlcyBhbGwgdGhlIHZhbHVlcyBpbiB0aGUgb3JkZXIgdGhleSB3ZXJlXG4gIHBhc3NlZCBpbiB0aGUgYHByb21pc2VzYCBhcnJheSBhcmd1bWVudC5cblxuICBFeGFtcGxlOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgdmFyIHByb21pc2UxID0gUlNWUC5yZXNvbHZlKDEpO1xuICB2YXIgcHJvbWlzZTIgPSBSU1ZQLnJlc29sdmUoMik7XG4gIHZhciBwcm9taXNlMyA9IFJTVlAucmVzb2x2ZSgzKTtcbiAgdmFyIHByb21pc2VzID0gWyBwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzIF07XG5cbiAgUlNWUC5hbGwocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oYXJyYXkpe1xuICAgIC8vIFRoZSBhcnJheSBoZXJlIHdvdWxkIGJlIFsgMSwgMiwgMyBdO1xuICB9KTtcbiAgYGBgXG5cbiAgSWYgYW55IG9mIHRoZSBgcHJvbWlzZXNgIGdpdmVuIHRvIGBSU1ZQLmFsbGAgYXJlIHJlamVjdGVkLCB0aGUgZmlyc3QgcHJvbWlzZVxuICB0aGF0IGlzIHJlamVjdGVkIHdpbGwgYmUgZ2l2ZW4gYXMgYW4gYXJndW1lbnQgdG8gdGhlIHJldHVybmVkIHByb21pc2VzJ3NcbiAgcmVqZWN0aW9uIGhhbmRsZXIuIEZvciBleGFtcGxlOlxuXG4gIEV4YW1wbGU6XG5cbiAgYGBgamF2YXNjcmlwdFxuICB2YXIgcHJvbWlzZTEgPSBSU1ZQLnJlc29sdmUoMSk7XG4gIHZhciBwcm9taXNlMiA9IFJTVlAucmVqZWN0KG5ldyBFcnJvcihcIjJcIikpO1xuICB2YXIgcHJvbWlzZTMgPSBSU1ZQLnJlamVjdChuZXcgRXJyb3IoXCIzXCIpKTtcbiAgdmFyIHByb21pc2VzID0gWyBwcm9taXNlMSwgcHJvbWlzZTIsIHByb21pc2UzIF07XG5cbiAgUlNWUC5hbGwocHJvbWlzZXMpLnRoZW4oZnVuY3Rpb24oYXJyYXkpe1xuICAgIC8vIENvZGUgaGVyZSBuZXZlciBydW5zIGJlY2F1c2UgdGhlcmUgYXJlIHJlamVjdGVkIHByb21pc2VzIVxuICB9LCBmdW5jdGlvbihlcnJvcikge1xuICAgIC8vIGVycm9yLm1lc3NhZ2UgPT09IFwiMlwiXG4gIH0pO1xuICBgYGBcblxuICBAbWV0aG9kIGFsbFxuICBAZm9yIFJTVlBcbiAgQHBhcmFtIHtBcnJheX0gcHJvbWlzZXNcbiAgQHBhcmFtIHtTdHJpbmd9IGxhYmVsXG4gIEByZXR1cm4ge1Byb21pc2V9IHByb21pc2UgdGhhdCBpcyBmdWxmaWxsZWQgd2hlbiBhbGwgYHByb21pc2VzYCBoYXZlIGJlZW5cbiAgZnVsZmlsbGVkLCBvciByZWplY3RlZCBpZiBhbnkgb2YgdGhlbSBiZWNvbWUgcmVqZWN0ZWQuXG4qL1xuZnVuY3Rpb24gYWxsKHByb21pc2VzKSB7XG4gIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG4gIHZhciBQcm9taXNlID0gdGhpcztcblxuICBpZiAoIWlzQXJyYXkocHJvbWlzZXMpKSB7XG4gICAgdGhyb3cgbmV3IFR5cGVFcnJvcignWW91IG11c3QgcGFzcyBhbiBhcnJheSB0byBhbGwuJyk7XG4gIH1cblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFyIHJlc3VsdHMgPSBbXSwgcmVtYWluaW5nID0gcHJvbWlzZXMubGVuZ3RoLFxuICAgIHByb21pc2U7XG5cbiAgICBpZiAocmVtYWluaW5nID09PSAwKSB7XG4gICAgICByZXNvbHZlKFtdKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiByZXNvbHZlcihpbmRleCkge1xuICAgICAgcmV0dXJuIGZ1bmN0aW9uKHZhbHVlKSB7XG4gICAgICAgIHJlc29sdmVBbGwoaW5kZXgsIHZhbHVlKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVzb2x2ZUFsbChpbmRleCwgdmFsdWUpIHtcbiAgICAgIHJlc3VsdHNbaW5kZXhdID0gdmFsdWU7XG4gICAgICBpZiAoLS1yZW1haW5pbmcgPT09IDApIHtcbiAgICAgICAgcmVzb2x2ZShyZXN1bHRzKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBmb3IgKHZhciBpID0gMDsgaSA8IHByb21pc2VzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBwcm9taXNlID0gcHJvbWlzZXNbaV07XG5cbiAgICAgIGlmIChwcm9taXNlICYmIGlzRnVuY3Rpb24ocHJvbWlzZS50aGVuKSkge1xuICAgICAgICBwcm9taXNlLnRoZW4ocmVzb2x2ZXIoaSksIHJlamVjdCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXNvbHZlQWxsKGksIHByb21pc2UpO1xuICAgICAgfVxuICAgIH1cbiAgfSk7XG59XG5cbmV4cG9ydHMuYWxsID0gYWxsOyIsIihmdW5jdGlvbiAocHJvY2VzcyxnbG9iYWwpe1xuXCJ1c2Ugc3RyaWN0XCI7XG52YXIgYnJvd3Nlckdsb2JhbCA9ICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykgPyB3aW5kb3cgOiB7fTtcbnZhciBCcm93c2VyTXV0YXRpb25PYnNlcnZlciA9IGJyb3dzZXJHbG9iYWwuTXV0YXRpb25PYnNlcnZlciB8fCBicm93c2VyR2xvYmFsLldlYktpdE11dGF0aW9uT2JzZXJ2ZXI7XG52YXIgbG9jYWwgPSAodHlwZW9mIGdsb2JhbCAhPT0gJ3VuZGVmaW5lZCcpID8gZ2xvYmFsIDogKHRoaXMgPT09IHVuZGVmaW5lZD8gd2luZG93OnRoaXMpO1xuXG4vLyBub2RlXG5mdW5jdGlvbiB1c2VOZXh0VGljaygpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIHByb2Nlc3MubmV4dFRpY2soZmx1c2gpO1xuICB9O1xufVxuXG5mdW5jdGlvbiB1c2VNdXRhdGlvbk9ic2VydmVyKCkge1xuICB2YXIgaXRlcmF0aW9ucyA9IDA7XG4gIHZhciBvYnNlcnZlciA9IG5ldyBCcm93c2VyTXV0YXRpb25PYnNlcnZlcihmbHVzaCk7XG4gIHZhciBub2RlID0gZG9jdW1lbnQuY3JlYXRlVGV4dE5vZGUoJycpO1xuICBvYnNlcnZlci5vYnNlcnZlKG5vZGUsIHsgY2hhcmFjdGVyRGF0YTogdHJ1ZSB9KTtcblxuICByZXR1cm4gZnVuY3Rpb24oKSB7XG4gICAgbm9kZS5kYXRhID0gKGl0ZXJhdGlvbnMgPSArK2l0ZXJhdGlvbnMgJSAyKTtcbiAgfTtcbn1cblxuZnVuY3Rpb24gdXNlU2V0VGltZW91dCgpIHtcbiAgcmV0dXJuIGZ1bmN0aW9uKCkge1xuICAgIGxvY2FsLnNldFRpbWVvdXQoZmx1c2gsIDEpO1xuICB9O1xufVxuXG52YXIgcXVldWUgPSBbXTtcbmZ1bmN0aW9uIGZsdXNoKCkge1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHF1ZXVlLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHR1cGxlID0gcXVldWVbaV07XG4gICAgdmFyIGNhbGxiYWNrID0gdHVwbGVbMF0sIGFyZyA9IHR1cGxlWzFdO1xuICAgIGNhbGxiYWNrKGFyZyk7XG4gIH1cbiAgcXVldWUgPSBbXTtcbn1cblxudmFyIHNjaGVkdWxlRmx1c2g7XG5cbi8vIERlY2lkZSB3aGF0IGFzeW5jIG1ldGhvZCB0byB1c2UgdG8gdHJpZ2dlcmluZyBwcm9jZXNzaW5nIG9mIHF1ZXVlZCBjYWxsYmFja3M6XG5pZiAodHlwZW9mIHByb2Nlc3MgIT09ICd1bmRlZmluZWQnICYmIHt9LnRvU3RyaW5nLmNhbGwocHJvY2VzcykgPT09ICdbb2JqZWN0IHByb2Nlc3NdJykge1xuICBzY2hlZHVsZUZsdXNoID0gdXNlTmV4dFRpY2soKTtcbn0gZWxzZSBpZiAoQnJvd3Nlck11dGF0aW9uT2JzZXJ2ZXIpIHtcbiAgc2NoZWR1bGVGbHVzaCA9IHVzZU11dGF0aW9uT2JzZXJ2ZXIoKTtcbn0gZWxzZSB7XG4gIHNjaGVkdWxlRmx1c2ggPSB1c2VTZXRUaW1lb3V0KCk7XG59XG5cbmZ1bmN0aW9uIGFzYXAoY2FsbGJhY2ssIGFyZykge1xuICB2YXIgbGVuZ3RoID0gcXVldWUucHVzaChbY2FsbGJhY2ssIGFyZ10pO1xuICBpZiAobGVuZ3RoID09PSAxKSB7XG4gICAgLy8gSWYgbGVuZ3RoIGlzIDEsIHRoYXQgbWVhbnMgdGhhdCB3ZSBuZWVkIHRvIHNjaGVkdWxlIGFuIGFzeW5jIGZsdXNoLlxuICAgIC8vIElmIGFkZGl0aW9uYWwgY2FsbGJhY2tzIGFyZSBxdWV1ZWQgYmVmb3JlIHRoZSBxdWV1ZSBpcyBmbHVzaGVkLCB0aGV5XG4gICAgLy8gd2lsbCBiZSBwcm9jZXNzZWQgYnkgdGhpcyBmbHVzaCB0aGF0IHdlIGFyZSBzY2hlZHVsaW5nLlxuICAgIHNjaGVkdWxlRmx1c2goKTtcbiAgfVxufVxuXG5leHBvcnRzLmFzYXAgPSBhc2FwO1xufSkuY2FsbCh0aGlzLHJlcXVpcmUoXCIweVBEMy9cIiksdHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHt9KSIsIlwidXNlIHN0cmljdFwiO1xudmFyIGNvbmZpZyA9IHtcbiAgaW5zdHJ1bWVudDogZmFsc2Vcbn07XG5cbmZ1bmN0aW9uIGNvbmZpZ3VyZShuYW1lLCB2YWx1ZSkge1xuICBpZiAoYXJndW1lbnRzLmxlbmd0aCA9PT0gMikge1xuICAgIGNvbmZpZ1tuYW1lXSA9IHZhbHVlO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBjb25maWdbbmFtZV07XG4gIH1cbn1cblxuZXhwb3J0cy5jb25maWcgPSBjb25maWc7XG5leHBvcnRzLmNvbmZpZ3VyZSA9IGNvbmZpZ3VyZTsiLCIoZnVuY3Rpb24gKGdsb2JhbCl7XG5cInVzZSBzdHJpY3RcIjtcbi8qZ2xvYmFsIHNlbGYqL1xudmFyIFJTVlBQcm9taXNlID0gcmVxdWlyZShcIi4vcHJvbWlzZVwiKS5Qcm9taXNlO1xudmFyIGlzRnVuY3Rpb24gPSByZXF1aXJlKFwiLi91dGlsc1wiKS5pc0Z1bmN0aW9uO1xuXG5mdW5jdGlvbiBwb2x5ZmlsbCgpIHtcbiAgdmFyIGxvY2FsO1xuXG4gIGlmICh0eXBlb2YgZ2xvYmFsICE9PSAndW5kZWZpbmVkJykge1xuICAgIGxvY2FsID0gZ2xvYmFsO1xuICB9IGVsc2UgaWYgKHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmIHdpbmRvdy5kb2N1bWVudCkge1xuICAgIGxvY2FsID0gd2luZG93O1xuICB9IGVsc2Uge1xuICAgIGxvY2FsID0gc2VsZjtcbiAgfVxuXG4gIHZhciBlczZQcm9taXNlU3VwcG9ydCA9IFxuICAgIFwiUHJvbWlzZVwiIGluIGxvY2FsICYmXG4gICAgLy8gU29tZSBvZiB0aGVzZSBtZXRob2RzIGFyZSBtaXNzaW5nIGZyb21cbiAgICAvLyBGaXJlZm94L0Nocm9tZSBleHBlcmltZW50YWwgaW1wbGVtZW50YXRpb25zXG4gICAgXCJyZXNvbHZlXCIgaW4gbG9jYWwuUHJvbWlzZSAmJlxuICAgIFwicmVqZWN0XCIgaW4gbG9jYWwuUHJvbWlzZSAmJlxuICAgIFwiYWxsXCIgaW4gbG9jYWwuUHJvbWlzZSAmJlxuICAgIFwicmFjZVwiIGluIGxvY2FsLlByb21pc2UgJiZcbiAgICAvLyBPbGRlciB2ZXJzaW9uIG9mIHRoZSBzcGVjIGhhZCBhIHJlc29sdmVyIG9iamVjdFxuICAgIC8vIGFzIHRoZSBhcmcgcmF0aGVyIHRoYW4gYSBmdW5jdGlvblxuICAgIChmdW5jdGlvbigpIHtcbiAgICAgIHZhciByZXNvbHZlO1xuICAgICAgbmV3IGxvY2FsLlByb21pc2UoZnVuY3Rpb24ocikgeyByZXNvbHZlID0gcjsgfSk7XG4gICAgICByZXR1cm4gaXNGdW5jdGlvbihyZXNvbHZlKTtcbiAgICB9KCkpO1xuXG4gIGlmICghZXM2UHJvbWlzZVN1cHBvcnQpIHtcbiAgICBsb2NhbC5Qcm9taXNlID0gUlNWUFByb21pc2U7XG4gIH1cbn1cblxuZXhwb3J0cy5wb2x5ZmlsbCA9IHBvbHlmaWxsO1xufSkuY2FsbCh0aGlzLHR5cGVvZiBzZWxmICE9PSBcInVuZGVmaW5lZFwiID8gc2VsZiA6IHR5cGVvZiB3aW5kb3cgIT09IFwidW5kZWZpbmVkXCIgPyB3aW5kb3cgOiB7fSkiLCJcInVzZSBzdHJpY3RcIjtcbnZhciBjb25maWcgPSByZXF1aXJlKFwiLi9jb25maWdcIikuY29uZmlnO1xudmFyIGNvbmZpZ3VyZSA9IHJlcXVpcmUoXCIuL2NvbmZpZ1wiKS5jb25maWd1cmU7XG52YXIgb2JqZWN0T3JGdW5jdGlvbiA9IHJlcXVpcmUoXCIuL3V0aWxzXCIpLm9iamVjdE9yRnVuY3Rpb247XG52YXIgaXNGdW5jdGlvbiA9IHJlcXVpcmUoXCIuL3V0aWxzXCIpLmlzRnVuY3Rpb247XG52YXIgbm93ID0gcmVxdWlyZShcIi4vdXRpbHNcIikubm93O1xudmFyIGFsbCA9IHJlcXVpcmUoXCIuL2FsbFwiKS5hbGw7XG52YXIgcmFjZSA9IHJlcXVpcmUoXCIuL3JhY2VcIikucmFjZTtcbnZhciBzdGF0aWNSZXNvbHZlID0gcmVxdWlyZShcIi4vcmVzb2x2ZVwiKS5yZXNvbHZlO1xudmFyIHN0YXRpY1JlamVjdCA9IHJlcXVpcmUoXCIuL3JlamVjdFwiKS5yZWplY3Q7XG52YXIgYXNhcCA9IHJlcXVpcmUoXCIuL2FzYXBcIikuYXNhcDtcblxudmFyIGNvdW50ZXIgPSAwO1xuXG5jb25maWcuYXN5bmMgPSBhc2FwOyAvLyBkZWZhdWx0IGFzeW5jIGlzIGFzYXA7XG5cbmZ1bmN0aW9uIFByb21pc2UocmVzb2x2ZXIpIHtcbiAgaWYgKCFpc0Z1bmN0aW9uKHJlc29sdmVyKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1lvdSBtdXN0IHBhc3MgYSByZXNvbHZlciBmdW5jdGlvbiBhcyB0aGUgZmlyc3QgYXJndW1lbnQgdG8gdGhlIHByb21pc2UgY29uc3RydWN0b3InKTtcbiAgfVxuXG4gIGlmICghKHRoaXMgaW5zdGFuY2VvZiBQcm9taXNlKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJGYWlsZWQgdG8gY29uc3RydWN0ICdQcm9taXNlJzogUGxlYXNlIHVzZSB0aGUgJ25ldycgb3BlcmF0b3IsIHRoaXMgb2JqZWN0IGNvbnN0cnVjdG9yIGNhbm5vdCBiZSBjYWxsZWQgYXMgYSBmdW5jdGlvbi5cIik7XG4gIH1cblxuICB0aGlzLl9zdWJzY3JpYmVycyA9IFtdO1xuXG4gIGludm9rZVJlc29sdmVyKHJlc29sdmVyLCB0aGlzKTtcbn1cblxuZnVuY3Rpb24gaW52b2tlUmVzb2x2ZXIocmVzb2x2ZXIsIHByb21pc2UpIHtcbiAgZnVuY3Rpb24gcmVzb2x2ZVByb21pc2UodmFsdWUpIHtcbiAgICByZXNvbHZlKHByb21pc2UsIHZhbHVlKTtcbiAgfVxuXG4gIGZ1bmN0aW9uIHJlamVjdFByb21pc2UocmVhc29uKSB7XG4gICAgcmVqZWN0KHByb21pc2UsIHJlYXNvbik7XG4gIH1cblxuICB0cnkge1xuICAgIHJlc29sdmVyKHJlc29sdmVQcm9taXNlLCByZWplY3RQcm9taXNlKTtcbiAgfSBjYXRjaChlKSB7XG4gICAgcmVqZWN0UHJvbWlzZShlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpbnZva2VDYWxsYmFjayhzZXR0bGVkLCBwcm9taXNlLCBjYWxsYmFjaywgZGV0YWlsKSB7XG4gIHZhciBoYXNDYWxsYmFjayA9IGlzRnVuY3Rpb24oY2FsbGJhY2spLFxuICAgICAgdmFsdWUsIGVycm9yLCBzdWNjZWVkZWQsIGZhaWxlZDtcblxuICBpZiAoaGFzQ2FsbGJhY2spIHtcbiAgICB0cnkge1xuICAgICAgdmFsdWUgPSBjYWxsYmFjayhkZXRhaWwpO1xuICAgICAgc3VjY2VlZGVkID0gdHJ1ZTtcbiAgICB9IGNhdGNoKGUpIHtcbiAgICAgIGZhaWxlZCA9IHRydWU7XG4gICAgICBlcnJvciA9IGU7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHZhbHVlID0gZGV0YWlsO1xuICAgIHN1Y2NlZWRlZCA9IHRydWU7XG4gIH1cblxuICBpZiAoaGFuZGxlVGhlbmFibGUocHJvbWlzZSwgdmFsdWUpKSB7XG4gICAgcmV0dXJuO1xuICB9IGVsc2UgaWYgKGhhc0NhbGxiYWNrICYmIHN1Y2NlZWRlZCkge1xuICAgIHJlc29sdmUocHJvbWlzZSwgdmFsdWUpO1xuICB9IGVsc2UgaWYgKGZhaWxlZCkge1xuICAgIHJlamVjdChwcm9taXNlLCBlcnJvcik7XG4gIH0gZWxzZSBpZiAoc2V0dGxlZCA9PT0gRlVMRklMTEVEKSB7XG4gICAgcmVzb2x2ZShwcm9taXNlLCB2YWx1ZSk7XG4gIH0gZWxzZSBpZiAoc2V0dGxlZCA9PT0gUkVKRUNURUQpIHtcbiAgICByZWplY3QocHJvbWlzZSwgdmFsdWUpO1xuICB9XG59XG5cbnZhciBQRU5ESU5HICAgPSB2b2lkIDA7XG52YXIgU0VBTEVEICAgID0gMDtcbnZhciBGVUxGSUxMRUQgPSAxO1xudmFyIFJFSkVDVEVEICA9IDI7XG5cbmZ1bmN0aW9uIHN1YnNjcmliZShwYXJlbnQsIGNoaWxkLCBvbkZ1bGZpbGxtZW50LCBvblJlamVjdGlvbikge1xuICB2YXIgc3Vic2NyaWJlcnMgPSBwYXJlbnQuX3N1YnNjcmliZXJzO1xuICB2YXIgbGVuZ3RoID0gc3Vic2NyaWJlcnMubGVuZ3RoO1xuXG4gIHN1YnNjcmliZXJzW2xlbmd0aF0gPSBjaGlsZDtcbiAgc3Vic2NyaWJlcnNbbGVuZ3RoICsgRlVMRklMTEVEXSA9IG9uRnVsZmlsbG1lbnQ7XG4gIHN1YnNjcmliZXJzW2xlbmd0aCArIFJFSkVDVEVEXSAgPSBvblJlamVjdGlvbjtcbn1cblxuZnVuY3Rpb24gcHVibGlzaChwcm9taXNlLCBzZXR0bGVkKSB7XG4gIHZhciBjaGlsZCwgY2FsbGJhY2ssIHN1YnNjcmliZXJzID0gcHJvbWlzZS5fc3Vic2NyaWJlcnMsIGRldGFpbCA9IHByb21pc2UuX2RldGFpbDtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHN1YnNjcmliZXJzLmxlbmd0aDsgaSArPSAzKSB7XG4gICAgY2hpbGQgPSBzdWJzY3JpYmVyc1tpXTtcbiAgICBjYWxsYmFjayA9IHN1YnNjcmliZXJzW2kgKyBzZXR0bGVkXTtcblxuICAgIGludm9rZUNhbGxiYWNrKHNldHRsZWQsIGNoaWxkLCBjYWxsYmFjaywgZGV0YWlsKTtcbiAgfVxuXG4gIHByb21pc2UuX3N1YnNjcmliZXJzID0gbnVsbDtcbn1cblxuUHJvbWlzZS5wcm90b3R5cGUgPSB7XG4gIGNvbnN0cnVjdG9yOiBQcm9taXNlLFxuXG4gIF9zdGF0ZTogdW5kZWZpbmVkLFxuICBfZGV0YWlsOiB1bmRlZmluZWQsXG4gIF9zdWJzY3JpYmVyczogdW5kZWZpbmVkLFxuXG4gIHRoZW46IGZ1bmN0aW9uKG9uRnVsZmlsbG1lbnQsIG9uUmVqZWN0aW9uKSB7XG4gICAgdmFyIHByb21pc2UgPSB0aGlzO1xuXG4gICAgdmFyIHRoZW5Qcm9taXNlID0gbmV3IHRoaXMuY29uc3RydWN0b3IoZnVuY3Rpb24oKSB7fSk7XG5cbiAgICBpZiAodGhpcy5fc3RhdGUpIHtcbiAgICAgIHZhciBjYWxsYmFja3MgPSBhcmd1bWVudHM7XG4gICAgICBjb25maWcuYXN5bmMoZnVuY3Rpb24gaW52b2tlUHJvbWlzZUNhbGxiYWNrKCkge1xuICAgICAgICBpbnZva2VDYWxsYmFjayhwcm9taXNlLl9zdGF0ZSwgdGhlblByb21pc2UsIGNhbGxiYWNrc1twcm9taXNlLl9zdGF0ZSAtIDFdLCBwcm9taXNlLl9kZXRhaWwpO1xuICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN1YnNjcmliZSh0aGlzLCB0aGVuUHJvbWlzZSwgb25GdWxmaWxsbWVudCwgb25SZWplY3Rpb24pO1xuICAgIH1cblxuICAgIHJldHVybiB0aGVuUHJvbWlzZTtcbiAgfSxcblxuICAnY2F0Y2gnOiBmdW5jdGlvbihvblJlamVjdGlvbikge1xuICAgIHJldHVybiB0aGlzLnRoZW4obnVsbCwgb25SZWplY3Rpb24pO1xuICB9XG59O1xuXG5Qcm9taXNlLmFsbCA9IGFsbDtcblByb21pc2UucmFjZSA9IHJhY2U7XG5Qcm9taXNlLnJlc29sdmUgPSBzdGF0aWNSZXNvbHZlO1xuUHJvbWlzZS5yZWplY3QgPSBzdGF0aWNSZWplY3Q7XG5cbmZ1bmN0aW9uIGhhbmRsZVRoZW5hYmxlKHByb21pc2UsIHZhbHVlKSB7XG4gIHZhciB0aGVuID0gbnVsbCxcbiAgcmVzb2x2ZWQ7XG5cbiAgdHJ5IHtcbiAgICBpZiAocHJvbWlzZSA9PT0gdmFsdWUpIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJBIHByb21pc2VzIGNhbGxiYWNrIGNhbm5vdCByZXR1cm4gdGhhdCBzYW1lIHByb21pc2UuXCIpO1xuICAgIH1cblxuICAgIGlmIChvYmplY3RPckZ1bmN0aW9uKHZhbHVlKSkge1xuICAgICAgdGhlbiA9IHZhbHVlLnRoZW47XG5cbiAgICAgIGlmIChpc0Z1bmN0aW9uKHRoZW4pKSB7XG4gICAgICAgIHRoZW4uY2FsbCh2YWx1ZSwgZnVuY3Rpb24odmFsKSB7XG4gICAgICAgICAgaWYgKHJlc29sdmVkKSB7IHJldHVybiB0cnVlOyB9XG4gICAgICAgICAgcmVzb2x2ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgaWYgKHZhbHVlICE9PSB2YWwpIHtcbiAgICAgICAgICAgIHJlc29sdmUocHJvbWlzZSwgdmFsKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZnVsZmlsbChwcm9taXNlLCB2YWwpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSwgZnVuY3Rpb24odmFsKSB7XG4gICAgICAgICAgaWYgKHJlc29sdmVkKSB7IHJldHVybiB0cnVlOyB9XG4gICAgICAgICAgcmVzb2x2ZWQgPSB0cnVlO1xuXG4gICAgICAgICAgcmVqZWN0KHByb21pc2UsIHZhbCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICBpZiAocmVzb2x2ZWQpIHsgcmV0dXJuIHRydWU7IH1cbiAgICByZWplY3QocHJvbWlzZSwgZXJyb3IpO1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiByZXNvbHZlKHByb21pc2UsIHZhbHVlKSB7XG4gIGlmIChwcm9taXNlID09PSB2YWx1ZSkge1xuICAgIGZ1bGZpbGwocHJvbWlzZSwgdmFsdWUpO1xuICB9IGVsc2UgaWYgKCFoYW5kbGVUaGVuYWJsZShwcm9taXNlLCB2YWx1ZSkpIHtcbiAgICBmdWxmaWxsKHByb21pc2UsIHZhbHVlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBmdWxmaWxsKHByb21pc2UsIHZhbHVlKSB7XG4gIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gUEVORElORykgeyByZXR1cm47IH1cbiAgcHJvbWlzZS5fc3RhdGUgPSBTRUFMRUQ7XG4gIHByb21pc2UuX2RldGFpbCA9IHZhbHVlO1xuXG4gIGNvbmZpZy5hc3luYyhwdWJsaXNoRnVsZmlsbG1lbnQsIHByb21pc2UpO1xufVxuXG5mdW5jdGlvbiByZWplY3QocHJvbWlzZSwgcmVhc29uKSB7XG4gIGlmIChwcm9taXNlLl9zdGF0ZSAhPT0gUEVORElORykgeyByZXR1cm47IH1cbiAgcHJvbWlzZS5fc3RhdGUgPSBTRUFMRUQ7XG4gIHByb21pc2UuX2RldGFpbCA9IHJlYXNvbjtcblxuICBjb25maWcuYXN5bmMocHVibGlzaFJlamVjdGlvbiwgcHJvbWlzZSk7XG59XG5cbmZ1bmN0aW9uIHB1Ymxpc2hGdWxmaWxsbWVudChwcm9taXNlKSB7XG4gIHB1Ymxpc2gocHJvbWlzZSwgcHJvbWlzZS5fc3RhdGUgPSBGVUxGSUxMRUQpO1xufVxuXG5mdW5jdGlvbiBwdWJsaXNoUmVqZWN0aW9uKHByb21pc2UpIHtcbiAgcHVibGlzaChwcm9taXNlLCBwcm9taXNlLl9zdGF0ZSA9IFJFSkVDVEVEKTtcbn1cblxuZXhwb3J0cy5Qcm9taXNlID0gUHJvbWlzZTsiLCJcInVzZSBzdHJpY3RcIjtcbi8qIGdsb2JhbCB0b1N0cmluZyAqL1xudmFyIGlzQXJyYXkgPSByZXF1aXJlKFwiLi91dGlsc1wiKS5pc0FycmF5O1xuXG4vKipcbiAgYFJTVlAucmFjZWAgYWxsb3dzIHlvdSB0byB3YXRjaCBhIHNlcmllcyBvZiBwcm9taXNlcyBhbmQgYWN0IGFzIHNvb24gYXMgdGhlXG4gIGZpcnN0IHByb21pc2UgZ2l2ZW4gdG8gdGhlIGBwcm9taXNlc2AgYXJndW1lbnQgZnVsZmlsbHMgb3IgcmVqZWN0cy5cblxuICBFeGFtcGxlOlxuXG4gIGBgYGphdmFzY3JpcHRcbiAgdmFyIHByb21pc2UxID0gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcbiAgICAgIHJlc29sdmUoXCJwcm9taXNlIDFcIik7XG4gICAgfSwgMjAwKTtcbiAgfSk7XG5cbiAgdmFyIHByb21pc2UyID0gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgIHNldFRpbWVvdXQoZnVuY3Rpb24oKXtcbiAgICAgIHJlc29sdmUoXCJwcm9taXNlIDJcIik7XG4gICAgfSwgMTAwKTtcbiAgfSk7XG5cbiAgUlNWUC5yYWNlKFtwcm9taXNlMSwgcHJvbWlzZTJdKS50aGVuKGZ1bmN0aW9uKHJlc3VsdCl7XG4gICAgLy8gcmVzdWx0ID09PSBcInByb21pc2UgMlwiIGJlY2F1c2UgaXQgd2FzIHJlc29sdmVkIGJlZm9yZSBwcm9taXNlMVxuICAgIC8vIHdhcyByZXNvbHZlZC5cbiAgfSk7XG4gIGBgYFxuXG4gIGBSU1ZQLnJhY2VgIGlzIGRldGVybWluaXN0aWMgaW4gdGhhdCBvbmx5IHRoZSBzdGF0ZSBvZiB0aGUgZmlyc3QgY29tcGxldGVkXG4gIHByb21pc2UgbWF0dGVycy4gRm9yIGV4YW1wbGUsIGV2ZW4gaWYgb3RoZXIgcHJvbWlzZXMgZ2l2ZW4gdG8gdGhlIGBwcm9taXNlc2BcbiAgYXJyYXkgYXJndW1lbnQgYXJlIHJlc29sdmVkLCBidXQgdGhlIGZpcnN0IGNvbXBsZXRlZCBwcm9taXNlIGhhcyBiZWNvbWVcbiAgcmVqZWN0ZWQgYmVmb3JlIHRoZSBvdGhlciBwcm9taXNlcyBiZWNhbWUgZnVsZmlsbGVkLCB0aGUgcmV0dXJuZWQgcHJvbWlzZVxuICB3aWxsIGJlY29tZSByZWplY3RlZDpcblxuICBgYGBqYXZhc2NyaXB0XG4gIHZhciBwcm9taXNlMSA9IG5ldyBSU1ZQLlByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICByZXNvbHZlKFwicHJvbWlzZSAxXCIpO1xuICAgIH0sIDIwMCk7XG4gIH0pO1xuXG4gIHZhciBwcm9taXNlMiA9IG5ldyBSU1ZQLlByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KXtcbiAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7XG4gICAgICByZWplY3QobmV3IEVycm9yKFwicHJvbWlzZSAyXCIpKTtcbiAgICB9LCAxMDApO1xuICB9KTtcblxuICBSU1ZQLnJhY2UoW3Byb21pc2UxLCBwcm9taXNlMl0pLnRoZW4oZnVuY3Rpb24ocmVzdWx0KXtcbiAgICAvLyBDb2RlIGhlcmUgbmV2ZXIgcnVucyBiZWNhdXNlIHRoZXJlIGFyZSByZWplY3RlZCBwcm9taXNlcyFcbiAgfSwgZnVuY3Rpb24ocmVhc29uKXtcbiAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gXCJwcm9taXNlMlwiIGJlY2F1c2UgcHJvbWlzZSAyIGJlY2FtZSByZWplY3RlZCBiZWZvcmVcbiAgICAvLyBwcm9taXNlIDEgYmVjYW1lIGZ1bGZpbGxlZFxuICB9KTtcbiAgYGBgXG5cbiAgQG1ldGhvZCByYWNlXG4gIEBmb3IgUlNWUFxuICBAcGFyYW0ge0FycmF5fSBwcm9taXNlcyBhcnJheSBvZiBwcm9taXNlcyB0byBvYnNlcnZlXG4gIEBwYXJhbSB7U3RyaW5nfSBsYWJlbCBvcHRpb25hbCBzdHJpbmcgZm9yIGRlc2NyaWJpbmcgdGhlIHByb21pc2UgcmV0dXJuZWQuXG4gIFVzZWZ1bCBmb3IgdG9vbGluZy5cbiAgQHJldHVybiB7UHJvbWlzZX0gYSBwcm9taXNlIHRoYXQgYmVjb21lcyBmdWxmaWxsZWQgd2l0aCB0aGUgdmFsdWUgdGhlIGZpcnN0XG4gIGNvbXBsZXRlZCBwcm9taXNlcyBpcyByZXNvbHZlZCB3aXRoIGlmIHRoZSBmaXJzdCBjb21wbGV0ZWQgcHJvbWlzZSB3YXNcbiAgZnVsZmlsbGVkLCBvciByZWplY3RlZCB3aXRoIHRoZSByZWFzb24gdGhhdCB0aGUgZmlyc3QgY29tcGxldGVkIHByb21pc2VcbiAgd2FzIHJlamVjdGVkIHdpdGguXG4qL1xuZnVuY3Rpb24gcmFjZShwcm9taXNlcykge1xuICAvKmpzaGludCB2YWxpZHRoaXM6dHJ1ZSAqL1xuICB2YXIgUHJvbWlzZSA9IHRoaXM7XG5cbiAgaWYgKCFpc0FycmF5KHByb21pc2VzKSkge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ1lvdSBtdXN0IHBhc3MgYW4gYXJyYXkgdG8gcmFjZS4nKTtcbiAgfVxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24ocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdmFyIHJlc3VsdHMgPSBbXSwgcHJvbWlzZTtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcHJvbWlzZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIHByb21pc2UgPSBwcm9taXNlc1tpXTtcblxuICAgICAgaWYgKHByb21pc2UgJiYgdHlwZW9mIHByb21pc2UudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBwcm9taXNlLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc29sdmUocHJvbWlzZSk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuZXhwb3J0cy5yYWNlID0gcmFjZTsiLCJcInVzZSBzdHJpY3RcIjtcbi8qKlxuICBgUlNWUC5yZWplY3RgIHJldHVybnMgYSBwcm9taXNlIHRoYXQgd2lsbCBiZWNvbWUgcmVqZWN0ZWQgd2l0aCB0aGUgcGFzc2VkXG4gIGByZWFzb25gLiBgUlNWUC5yZWplY3RgIGlzIGVzc2VudGlhbGx5IHNob3J0aGFuZCBmb3IgdGhlIGZvbGxvd2luZzpcblxuICBgYGBqYXZhc2NyaXB0XG4gIHZhciBwcm9taXNlID0gbmV3IFJTVlAuUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgIHJlamVjdChuZXcgRXJyb3IoJ1dIT09QUycpKTtcbiAgfSk7XG5cbiAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAvLyBDb2RlIGhlcmUgZG9lc24ndCBydW4gYmVjYXVzZSB0aGUgcHJvbWlzZSBpcyByZWplY3RlZCFcbiAgfSwgZnVuY3Rpb24ocmVhc29uKXtcbiAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJ1dIT09QUydcbiAgfSk7XG4gIGBgYFxuXG4gIEluc3RlYWQgb2Ygd3JpdGluZyB0aGUgYWJvdmUsIHlvdXIgY29kZSBub3cgc2ltcGx5IGJlY29tZXMgdGhlIGZvbGxvd2luZzpcblxuICBgYGBqYXZhc2NyaXB0XG4gIHZhciBwcm9taXNlID0gUlNWUC5yZWplY3QobmV3IEVycm9yKCdXSE9PUFMnKSk7XG5cbiAgcHJvbWlzZS50aGVuKGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAvLyBDb2RlIGhlcmUgZG9lc24ndCBydW4gYmVjYXVzZSB0aGUgcHJvbWlzZSBpcyByZWplY3RlZCFcbiAgfSwgZnVuY3Rpb24ocmVhc29uKXtcbiAgICAvLyByZWFzb24ubWVzc2FnZSA9PT0gJ1dIT09QUydcbiAgfSk7XG4gIGBgYFxuXG4gIEBtZXRob2QgcmVqZWN0XG4gIEBmb3IgUlNWUFxuICBAcGFyYW0ge0FueX0gcmVhc29uIHZhbHVlIHRoYXQgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCBiZSByZWplY3RlZCB3aXRoLlxuICBAcGFyYW0ge1N0cmluZ30gbGFiZWwgb3B0aW9uYWwgc3RyaW5nIGZvciBpZGVudGlmeWluZyB0aGUgcmV0dXJuZWQgcHJvbWlzZS5cbiAgVXNlZnVsIGZvciB0b29saW5nLlxuICBAcmV0dXJuIHtQcm9taXNlfSBhIHByb21pc2UgdGhhdCB3aWxsIGJlY29tZSByZWplY3RlZCB3aXRoIHRoZSBnaXZlblxuICBgcmVhc29uYC5cbiovXG5mdW5jdGlvbiByZWplY3QocmVhc29uKSB7XG4gIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG4gIHZhciBQcm9taXNlID0gdGhpcztcblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIHJlamVjdChyZWFzb24pO1xuICB9KTtcbn1cblxuZXhwb3J0cy5yZWplY3QgPSByZWplY3Q7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5mdW5jdGlvbiByZXNvbHZlKHZhbHVlKSB7XG4gIC8qanNoaW50IHZhbGlkdGhpczp0cnVlICovXG4gIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlLmNvbnN0cnVjdG9yID09PSB0aGlzKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG5cbiAgdmFyIFByb21pc2UgPSB0aGlzO1xuXG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlKSB7XG4gICAgcmVzb2x2ZSh2YWx1ZSk7XG4gIH0pO1xufVxuXG5leHBvcnRzLnJlc29sdmUgPSByZXNvbHZlOyIsIlwidXNlIHN0cmljdFwiO1xuZnVuY3Rpb24gb2JqZWN0T3JGdW5jdGlvbih4KSB7XG4gIHJldHVybiBpc0Z1bmN0aW9uKHgpIHx8ICh0eXBlb2YgeCA9PT0gXCJvYmplY3RcIiAmJiB4ICE9PSBudWxsKTtcbn1cblxuZnVuY3Rpb24gaXNGdW5jdGlvbih4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gXCJmdW5jdGlvblwiO1xufVxuXG5mdW5jdGlvbiBpc0FycmF5KHgpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh4KSA9PT0gXCJbb2JqZWN0IEFycmF5XVwiO1xufVxuXG4vLyBEYXRlLm5vdyBpcyBub3QgYXZhaWxhYmxlIGluIGJyb3dzZXJzIDwgSUU5XG4vLyBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9KYXZhU2NyaXB0L1JlZmVyZW5jZS9HbG9iYWxfT2JqZWN0cy9EYXRlL25vdyNDb21wYXRpYmlsaXR5XG52YXIgbm93ID0gRGF0ZS5ub3cgfHwgZnVuY3Rpb24oKSB7IHJldHVybiBuZXcgRGF0ZSgpLmdldFRpbWUoKTsgfTtcblxuXG5leHBvcnRzLm9iamVjdE9yRnVuY3Rpb24gPSBvYmplY3RPckZ1bmN0aW9uO1xuZXhwb3J0cy5pc0Z1bmN0aW9uID0gaXNGdW5jdGlvbjtcbmV4cG9ydHMuaXNBcnJheSA9IGlzQXJyYXk7XG5leHBvcnRzLm5vdyA9IG5vdzsiLCJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vc3JjL2NyZWF0ZUNsaWVudCcpOyIsIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IobWVzc2FnZSl7XG4gIHRoaXMubmFtZSA9ICdEYXRhVHlwZVZhbGlkYXRpb25FcnJvcic7XG4gIHRoaXMubWVzc2FnZSA9IG1lc3NhZ2UgfHwgJ0ludmFsaWQgZGF0YSB0eXBlJztcbn1cbkRhdGFUeXBlVmFsaWRhdGlvbkVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRXJyb3IucHJvdG90eXBlKTtcbkRhdGFUeXBlVmFsaWRhdGlvbkVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IERhdGFUeXBlVmFsaWRhdGlvbkVycm9yO1xuZXhwb3J0cy5EYXRhVHlwZVZhbGlkYXRpb25FcnJvciA9IERhdGFUeXBlVmFsaWRhdGlvbkVycm9yO1xuXG5mdW5jdGlvbiBOb3RBbkludGVnZXJFcnJvcih2YWx1ZSl7XG4gIHRoaXMubmFtZSA9ICdOb3RBbkludGVnZXJFcnJvcic7XG4gIHRoaXMubWVzc2FnZSA9ICdcIicgKyB2YWx1ZSArICdcIiBpcyBub3QgYW4gaW50ZWdlcic7XG4gIHRoaXMudmFsdWUgPSB2YWx1ZTtcbn1cbk5vdEFuSW50ZWdlckVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlKTtcbk5vdEFuSW50ZWdlckVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE5vdEFuSW50ZWdlckVycm9yO1xuZXhwb3J0cy5Ob3RBbkludGVnZXJFcnJvciA9IE5vdEFuSW50ZWdlckVycm9yO1xuXG5mdW5jdGlvbiBOb3RBTnVtYmVyRXJyb3IodmFsdWUsIGFjdHVhbFR5cGUpe1xuICB0aGlzLm5hbWUgPSAnTm90QU51bWJlckVycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gJ1wiJyArIHZhbHVlICsgJ1wiIGlzIG5vdCBhIG51bWJlcic7XG4gIGlmKGFjdHVhbFR5cGUpIHRoaXMubWVzc2FnZSArPSAnIChnb3QgYSAnICsgYWN0dWFsVHlwZSArICcgaW5zdGVhZCknO1xuXG4gIHRoaXMudmFsdWUgPSB2YWx1ZTtcbn1cbk5vdEFOdW1iZXJFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKERhdGFUeXBlVmFsaWRhdGlvbkVycm9yLnByb3RvdHlwZSk7XG5Ob3RBTnVtYmVyRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTm90QU51bWJlckVycm9yO1xuZXhwb3J0cy5Ob3RBTnVtYmVyRXJyb3IgPSBOb3RBTnVtYmVyRXJyb3I7XG5cbmZ1bmN0aW9uIE51bWJlclRvb0xhcmdlRXJyb3IodmFsdWUsIG1heCl7XG4gIHRoaXMubmFtZSA9ICdOdW1iZXJUb29MYXJnZUVycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gJ1wiJyArIHZhbHVlICsgJ1wiIGlzIGFib3ZlIHRoZSBtYXhpbXVtIG9mICcgKyBtYXgudG9TdHJpbmcoKTtcbiAgdGhpcy52YWx1ZSA9IHZhbHVlO1xufVxuTnVtYmVyVG9vTGFyZ2VFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKERhdGFUeXBlVmFsaWRhdGlvbkVycm9yLnByb3RvdHlwZSk7XG5OdW1iZXJUb29MYXJnZUVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE51bWJlclRvb0xhcmdlRXJyb3I7XG5leHBvcnRzLk51bWJlclRvb0xhcmdlRXJyb3IgPSBOdW1iZXJUb29MYXJnZUVycm9yO1xuXG5mdW5jdGlvbiBOdW1iZXJUb29TbWFsbEVycm9yKHZhbHVlLCBtYXgpe1xuICB0aGlzLm5hbWUgPSAnTnVtYmVyVG9vU21hbGxFcnJvcic7XG4gIHRoaXMubWVzc2FnZSA9ICdcIicgKyB2YWx1ZSArICdcIiBpcyBhYm92ZSB0aGUgbWF4aW11bSBvZiAnICsgbWF4LnRvU3RyaW5nKCk7XG4gIHRoaXMudmFsdWUgPSB2YWx1ZTtcbn1cbk51bWJlclRvb1NtYWxsRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShEYXRhVHlwZVZhbGlkYXRpb25FcnJvci5wcm90b3R5cGUpO1xuTnVtYmVyVG9vU21hbGxFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBOdW1iZXJUb29TbWFsbEVycm9yO1xuZXhwb3J0cy5OdW1iZXJUb29TbWFsbEVycm9yID0gTnVtYmVyVG9vU21hbGxFcnJvcjtcblxuZnVuY3Rpb24gTm90QUJvb2xlYW5FcnJvcih2YWx1ZSwgYWN0dWFsVHlwZSl7XG4gIHRoaXMubmFtZSA9ICdOb3RBQm9vbGVhbkVycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gJ1wiJyArIHZhbHVlICsgJ1wiIGlzIG5vdCBhIGJvb2xlYW4nO1xuICBpZihhY3R1YWxUeXBlKSB0aGlzLm1lc3NhZ2UgKz0gJyAoZ290IGEgJyArIGFjdHVhbFR5cGUgKyAnIGluc3RlYWQpJztcblxuICB0aGlzLnZhbHVlID0gdmFsdWU7XG59XG5Ob3RBQm9vbGVhbkVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlKTtcbk5vdEFCb29sZWFuRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTm90QUJvb2xlYW5FcnJvcjtcbmV4cG9ydHMuTm90QUJvb2xlYW5FcnJvciA9IE5vdEFCb29sZWFuRXJyb3I7XG5cbmZ1bmN0aW9uIE5vdEFuQXJyYXlFcnJvcih2YWx1ZSwgYWN0dWFsVHlwZSl7XG4gIHRoaXMubmFtZSA9ICdOb3RBbkFycmF5RXJyb3InO1xuICB0aGlzLm1lc3NhZ2UgPSAnXCInICsgdmFsdWUgKyAnXCIgaXMgbm90IGFuIGFycmF5JztcbiAgaWYoYWN0dWFsVHlwZSkgdGhpcy5tZXNzYWdlICs9ICcgKGdvdCBhICcgKyBhY3R1YWxUeXBlICsgJyBpbnN0ZWFkKSc7XG5cbiAgdGhpcy52YWx1ZSA9IHZhbHVlO1xufVxuTm90QW5BcnJheUVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlKTtcbk5vdEFuQXJyYXlFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBOb3RBbkFycmF5RXJyb3I7XG5leHBvcnRzLk5vdEFuQXJyYXlFcnJvciA9IE5vdEFuQXJyYXlFcnJvcjtcblxuZnVuY3Rpb24gRHVwbGljYXRlSW5TZXRFcnJvcihhcnIsIGR1cGVzKXtcbiAgdGhpcy5uYW1lID0gJ0R1cGxpY2F0ZUluU2V0RXJyb3InO1xuICB0aGlzLm1lc3NhZ2UgPSAnRHVwbGljYXRlcyAoXCInICsgZHVwZXMuam9pbignXCIsIFwiJykgKyAnXCIpIGZvdW5kIGluIHNldDogW1wiJyArIGFyci5qb2luKCdcIiwgXCInKSArICdcIic7XG4gIHRoaXMuZHVwZXMgPSBkdXBlcztcbiAgdGhpcy52YWx1ZSA9IGFycjtcbn1cbkR1cGxpY2F0ZUluU2V0RXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShEYXRhVHlwZVZhbGlkYXRpb25FcnJvci5wcm90b3R5cGUpO1xuRHVwbGljYXRlSW5TZXRFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBEdXBsaWNhdGVJblNldEVycm9yO1xuZXhwb3J0cy5EdXBsaWNhdGVJblNldEVycm9yID0gRHVwbGljYXRlSW5TZXRFcnJvcjtcblxuZnVuY3Rpb24gTm90Vm9pZEVycm9yKHZhbHVlLCBhY3R1YWxUeXBlKXtcbiAgdGhpcy5uYW1lID0gJ05vdFZvaWRFcnJvcic7XG4gIHRoaXMubWVzc2FnZSA9ICdcIicgKyB2YWx1ZSArICdcIiBpcyBub3QgbnVsbCBvciB1bmRlZmluZWQnO1xuICBpZihhY3R1YWxUeXBlKSB0aGlzLm1lc3NhZ2UgKz0gJyAoZ290IGEgJyArIGFjdHVhbFR5cGUgKyAnIGluc3RlYWQpJztcblxuICB0aGlzLnZhbHVlID0gdmFsdWU7XG59XG5Ob3RWb2lkRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShEYXRhVHlwZVZhbGlkYXRpb25FcnJvci5wcm90b3R5cGUpO1xuTm90Vm9pZEVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE5vdFZvaWRFcnJvcjtcbmV4cG9ydHMuTm90Vm9pZEVycm9yID0gTm90Vm9pZEVycm9yO1xuXG5mdW5jdGlvbiBOb3RBU3RyaW5nRXJyb3IodmFsdWUsIGFjdHVhbFR5cGUpe1xuICB0aGlzLm5hbWUgPSAnTm90QVN0cmluZ0Vycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gJ1wiJyArIHZhbHVlICsgJ1wiIGlzIG5vdCBhIHN0cmluZyc7XG4gIGlmKGFjdHVhbFR5cGUpIHRoaXMubWVzc2FnZSArPSAnIChnb3QgYSAnICsgYWN0dWFsVHlwZSArICcgaW5zdGVhZCknO1xuXG4gIHRoaXMudmFsdWUgPSB2YWx1ZTtcbn1cbk5vdEFTdHJpbmdFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKERhdGFUeXBlVmFsaWRhdGlvbkVycm9yLnByb3RvdHlwZSk7XG5Ob3RBU3RyaW5nRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTm90QVN0cmluZ0Vycm9yO1xuZXhwb3J0cy5Ob3RBU3RyaW5nRXJyb3IgPSBOb3RBU3RyaW5nRXJyb3I7XG5cbmZ1bmN0aW9uIFN0cmluZ05vdEluRW51bUVycm9yKHZhbHVlLCBhY2NlcHRhYmxlVmFsdWVzKXtcbiAgdGhpcy5uYW1lID0gJ1N0cmluZ05vdEluRW51bUVycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gJ1wiJyArIHZhbHVlICsgJ1wiIGlzIG5vdCBhbiBhY2NlcHRhYmxlIHZhbHVlOiBcIicgKyBhY2NlcHRhYmxlVmFsdWVzLmpvaW4oJ1wiLCBcIicpICsgJ1wiJztcbiBcbiAgdGhpcy52YWx1ZSA9IHZhbHVlO1xufVxuU3RyaW5nTm90SW5FbnVtRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShEYXRhVHlwZVZhbGlkYXRpb25FcnJvci5wcm90b3R5cGUpO1xuU3RyaW5nTm90SW5FbnVtRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gU3RyaW5nTm90SW5FbnVtRXJyb3I7XG5leHBvcnRzLlN0cmluZ05vdEluRW51bUVycm9yID0gU3RyaW5nTm90SW5FbnVtRXJyb3I7XG5cblxuZnVuY3Rpb24gRXJyb3JzSW5BcnJheUVsZW1lbnRzRXJyb3IoZXJyb3JzKXtcbiAgdGhpcy5uYW1lID0gJ0Vycm9yc0luQXJyYXlFbGVtZW50c0Vycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gJ0Vycm9ycyBpbiBhcnJheSBlbGVtZW50czpcXG5cXHQnICsgZXJyb3JzLmpvaW4oJyxcXG5cXHQnKTtcbiAgdGhpcy5lcnJvcnMgPSBlcnJvcnM7XG59XG5FcnJvcnNJbkFycmF5RWxlbWVudHNFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKERhdGFUeXBlVmFsaWRhdGlvbkVycm9yLnByb3RvdHlwZSk7XG5FcnJvcnNJbkFycmF5RWxlbWVudHNFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBFcnJvcnNJbkFycmF5RWxlbWVudHNFcnJvcjtcbmV4cG9ydHMuRXJyb3JzSW5BcnJheUVsZW1lbnRzRXJyb3IgPSBFcnJvcnNJbkFycmF5RWxlbWVudHNFcnJvcjtcblxuZnVuY3Rpb24gTWlzc2luZ1ZhbHVlRXJyb3IoKXtcbiAgdGhpcy5uYW1lID0gJ01pc3NpbmdWYWx1ZUVycm9yJztcbiAgXG4gIHRoaXMubWVzc2FnZSA9ICdUaGlzIHZhbHVlIGlzIHJlcXVpcmVkIGJ1dCBtaXNzaW5nJztcbn1cbk1pc3NpbmdWYWx1ZUVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlKTtcbk1pc3NpbmdWYWx1ZUVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IE1pc3NpbmdWYWx1ZUVycm9yO1xuZXhwb3J0cy5NaXNzaW5nVmFsdWVFcnJvciA9IE1pc3NpbmdWYWx1ZUVycm9yO1xuXG5mdW5jdGlvbiBWYWxpZGF0aW9uRXJyb3Ioc3BlY05hbWUsIHNwZWMsIGVycm9yKXtcbiAgdGhpcy5uYW1lID0gJ1ZhbGlkYXRpb25FcnJvcic7XG4gIHRoaXMuc3BlY05hbWUgPSBzcGVjTmFtZTtcbiAgdGhpcy5zcGVjID0gc3BlYztcbiAgdGhpcy5lcnJvciA9IGVycm9yO1xuXG4gIHRoaXMubWVzc2FnZSA9IHNwZWNOYW1lICsgJyBpcyBpbnZhbGlkOiAnICsgZXJyb3IubWVzc2FnZTtcbn1cblZhbGlkYXRpb25FcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKERhdGFUeXBlVmFsaWRhdGlvbkVycm9yLnByb3RvdHlwZSk7XG5WYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gVmFsaWRhdGlvbkVycm9yO1xuZXhwb3J0cy5WYWxpZGF0aW9uRXJyb3IgPSBWYWxpZGF0aW9uRXJyb3I7XG5cbmZ1bmN0aW9uIFZhbGlkYXRpb25FcnJvcnModmFsdWUsIHNwZWNOYW1lLCBzcGVjLCBlcnJvcnMpe1xuICB0aGlzLm5hbWUgPSAnVmFsaWRhdGlvbkVycm9ycyc7XG5cbiAgdGhpcy52YWx1ZSA9IHZhbHVlO1xuICB0aGlzLnNwZWNOYW1lID0gc3BlY05hbWU7XG4gIHRoaXMuc3BlYyA9IHNwZWM7XG4gIHRoaXMuZXJyb3JzID0gZXJyb3JzIHx8IFtdO1xuXG4gIHRoaXMubWVzc2FnZSA9IHNwZWNOYW1lICsgJyBpcyBpbnZhbGlkJztcblxuICBpZih0aGlzLmVycm9ycy5sZW5ndGgpe1xuICAgIHRoaXMubWVzc2FnZSArPSAnOlxcblxcdCcgKyB0aGlzLmVycm9ycy5tYXAoZnVuY3Rpb24oZSl7IHJldHVybiBlLm1lc3NhZ2U7IH0pLmpvaW4oJ1xcblxcdCcpO1xuICB9XG59XG5WYWxpZGF0aW9uRXJyb3JzLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlKTtcblZhbGlkYXRpb25FcnJvcnMucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gVmFsaWRhdGlvbkVycm9ycztcbmV4cG9ydHMuVmFsaWRhdGlvbkVycm9ycyA9IFZhbGlkYXRpb25FcnJvcnM7XG4iLCJleHBvcnRzLmRhdGFUeXBlID0gcmVxdWlyZSgnLi92YWxpZGF0ZURhdGFUeXBlJyk7XG5leHBvcnRzLm1vZGVsID0gcmVxdWlyZSgnLi92YWxpZGF0ZU1vZGVsJyk7XG5leHBvcnRzLm9wZXJhdGlvbiA9IHJlcXVpcmUoJy4vdmFsaWRhdGVPcGVyYXRpb24nKTtcbmV4cG9ydHMuYXJyYXkgPSByZXF1aXJlKCcuL3ZhbGlkYXRlQXJyYXknKTtcbmV4cG9ydHMuZXJyb3JzID0gcmVxdWlyZSgnLi9lcnJvclR5cGVzJyk7XG5cbnZhciBwcmltaXRpdmVzID0gcmVxdWlyZSgnLi92YWxpZGF0ZVByaW1pdGl2ZVR5cGVzJyk7XG5leHBvcnRzLnByaW1pdGl2ZSA9IHtcbiAgaW50ZWdlcjogcHJpbWl0aXZlcy52YWxpZGF0ZUludGVnZXIsXG4gIG51bWJlcjogcHJpbWl0aXZlcy52YWxpZGF0ZU51bWJlcixcbiAgc3RyaW5nOiBwcmltaXRpdmVzLnZhbGlkYXRlU3RyaW5nLFxuICBib29sZWFuOiBwcmltaXRpdmVzLnZhbGlkYXRlQm9vbGVhbixcbiAgdm9pZDogcHJpbWl0aXZlcy52YWxpZGF0ZVZvaWQsXG4gIGZpbGU6IHByaW1pdGl2ZXMudmFsaWRhdGVGaWxlXG59O1xuIiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZXJyb3JUeXBlcyA9IHJlcXVpcmUoJy4vZXJyb3JUeXBlcycpLFxuICB2YWxpZGF0ZSA9IHJlcXVpcmUoJy4vaW5kZXgnKTtcblxuZnVuY3Rpb24gdmFsaWRhdGVBcnJheShjYW5kaWRhdGUsIGRhdGFUeXBlLCBtb2RlbHMpe1xuICBpZighQXJyYXkuaXNBcnJheShjYW5kaWRhdGUpKXtcbiAgICByZXR1cm4gbmV3IGVycm9yVHlwZXMuTm90QW5BcnJheUVycm9yKGNhbmRpZGF0ZSwgdHlwZW9mIGNhbmRpZGF0ZSk7XG4gIH1cblxuICB2YXIgaXRlbXMgPSBkYXRhVHlwZS5pdGVtcztcblxuICBpZihkYXRhVHlwZS51bmlxdWVJdGVtcyl7XG4gICAgdmFyIGR1cGVDaGVjayA9IFtdO1xuICAgIHZhciBkdXBlcyA9IGNhbmRpZGF0ZS5maWx0ZXIoZnVuY3Rpb24odmFsdWUpe1xuICAgICAgdmFyIHNpZ25hdHVyZTtcbiAgICAgIGlmKGl0ZW1zLiRyZWYpe1xuICAgICAgICBzaWduYXR1cmUgPSBKU09OLnN0cmluZ2lmeSh2YWx1ZSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBzaWduYXR1cmUgPSB2YWx1ZTtcbiAgICAgIH1cbiAgICAgIGlmKGR1cGVDaGVjay5pbmRleE9mKHNpZ25hdHVyZSkgIT09IC0xKXtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBkdXBlQ2hlY2sucHVzaChzaWduYXR1cmUpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZihkdXBlcy5sZW5ndGgpIHtcbiAgICAgIHJldHVybiBuZXcgZXJyb3JUeXBlcy5EdXBsaWNhdGVJblNldEVycm9yKGNhbmRpZGF0ZSwgZHVwZXMpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBlcnJvcnM7XG5cbiAgaWYoaXRlbXMuJHJlZil7XG4gICAgdmFyIG1vZGVsID0gbW9kZWxzW2l0ZW1zLiRyZWZdO1xuICAgIGVycm9ycyA9IGNhbmRpZGF0ZS5maWx0ZXIoZnVuY3Rpb24odmFsdWUpe1xuICAgICAgcmV0dXJuIHZhbGlkYXRlLm1vZGVsKHZhbHVlLCBtb2RlbCwgbW9kZWxzKTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBlcnJvcnMgPSBjYW5kaWRhdGUuZmlsdGVyKGZ1bmN0aW9uKHZhbHVlKXtcbiAgICAgIHJldHVybiB2YWxpZGF0ZS5kYXRhVHlwZSh2YWx1ZSwgaXRlbXMsIG1vZGVscyk7XG4gICAgfSk7XG4gIH1cblxuICBpZihlcnJvcnMubGVuZ3RoKXtcbiAgICByZXR1cm4gbmV3IGVycm9yVHlwZXMuRXJyb3JzSW5BcnJheUVsZW1lbnRzRXJyb3IoZXJyb3JzKTtcbiAgfVxufVxubW9kdWxlLmV4cG9ydHMgPSB2YWxpZGF0ZUFycmF5OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIHZhbGlkYXRlID0gcmVxdWlyZSgnLi9pbmRleCcpO1xuICBcbmZ1bmN0aW9uIHZhbGlkYXRlRGF0YVR5cGUoY2FuZGlkYXRlLCBkYXRhVHlwZSwgbW9kZWxzKXtcbiAgbW9kZWxzID0gbW9kZWxzIHx8IHt9O1xuICAgICAgXG4gIHZhciB0eXBlID0gZGF0YVR5cGUudHlwZSB8fCBkYXRhVHlwZS5kYXRhVHlwZSB8fCBkYXRhVHlwZS4kcmVmO1xuXG4gIHN3aXRjaCh0eXBlKXtcbiAgICBjYXNlICdpbnRlZ2VyJzpcbiAgICAgIHJldHVybiB2YWxpZGF0ZS5wcmltaXRpdmUuaW50ZWdlcihjYW5kaWRhdGUsIGRhdGFUeXBlKTtcbiAgICBjYXNlICdudW1iZXInOlxuICAgICAgcmV0dXJuIHZhbGlkYXRlLnByaW1pdGl2ZS5udW1iZXIoY2FuZGlkYXRlLCBkYXRhVHlwZSk7XG4gICAgY2FzZSAnc3RyaW5nJzpcbiAgICAgIHJldHVybiB2YWxpZGF0ZS5wcmltaXRpdmUuc3RyaW5nKGNhbmRpZGF0ZSwgZGF0YVR5cGUpO1xuICAgIGNhc2UgJ2Jvb2xlYW4nOlxuICAgICAgcmV0dXJuIHZhbGlkYXRlLnByaW1pdGl2ZS5ib29sZWFuKGNhbmRpZGF0ZSk7XG4gICAgY2FzZSAnYXJyYXknOlxuICAgICAgcmV0dXJuIHZhbGlkYXRlLmFycmF5KGNhbmRpZGF0ZSwgZGF0YVR5cGUsIG1vZGVscyk7XG4gICAgY2FzZSAndm9pZCc6XG4gICAgICByZXR1cm4gdmFsaWRhdGUucHJpbWl0aXZlLnZvaWQoY2FuZGlkYXRlKTtcbiAgICBjYXNlICdGaWxlJzpcbiAgICAgIHJldHVybiB2YWxpZGF0ZS5wcmltaXRpdmUuZmlsZSgpO1xuICAgIGRlZmF1bHQ6XG4gICAgICAvLyBBc3N1bWVkIHRvIGJlIGNvbXBsZXggbW9kZWxcbiAgICAgIHZhciBtb2RlbCA9IG1vZGVsc1t0eXBlXTtcbiAgICAgIHJldHVybiB2YWxpZGF0ZS5tb2RlbChjYW5kaWRhdGUsIG1vZGVsLCBtb2RlbHMpO1xuICB9XG59XG5tb2R1bGUuZXhwb3J0cyA9IHZhbGlkYXRlRGF0YVR5cGU7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZXJyb3JUeXBlcyA9IHJlcXVpcmUoJy4vZXJyb3JUeXBlcycpLFxuICBWYWxpZGF0aW9uRXJyb3IgPSBlcnJvclR5cGVzLlZhbGlkYXRpb25FcnJvcixcbiAgVmFsaWRhdGlvbkVycm9ycyA9IGVycm9yVHlwZXMuVmFsaWRhdGlvbkVycm9ycyxcbiAgTWlzc2luZ1ZhbHVlRXJyb3IgPSBlcnJvclR5cGVzLk1pc3NpbmdWYWx1ZUVycm9yLFxuICB2YWxpZGF0ZSA9IHJlcXVpcmUoJy4vaW5kZXgnKTtcblxuLy8gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy8xMjIxMDIvd2hhdC1pcy10aGUtbW9zdC1lZmZpY2llbnQtd2F5LXRvLWNsb25lLWFuLW9iamVjdFxuZnVuY3Rpb24gY2xvbmUob2JqKXtcbiAgICBpZihvYmogPT09IG51bGwgfHwgb2JqID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIG9iaiAhPT0gJ29iamVjdCcpIHJldHVybiBvYmo7XG5cbiAgICBpZihBcnJheS5pc0FycmF5KG9iaikpIHJldHVybiBvYmouc2xpY2UoKTtcblxuICAgIHZhciB0ZW1wID0ge307XG5cbiAgICBmb3IodmFyIGtleSBpbiBvYmopXG4gICAgICAgIHRlbXBba2V5XSA9IGNsb25lKG9ialtrZXldKTtcbiAgICByZXR1cm4gdGVtcDtcbn1cblxuZnVuY3Rpb24gYWRkSW5oZXJ0aWVkUHJvcGVydGllcyhtb2RlbCwgbW9kZWxJZCwgbW9kZWxzKXtcbiAgdmFyIHBhcmVudDtcblxuICBPYmplY3Qua2V5cyhtb2RlbHMpLnNvbWUoZnVuY3Rpb24obW9kZWxOYW1lKXtcbiAgICB2YXIgcG90ZW50aWFsUGFyZW50ID0gbW9kZWxzW21vZGVsTmFtZV07XG4gICAgaWYgKCFwb3RlbnRpYWxQYXJlbnQuc3ViVHlwZXMpIHJldHVybjtcblxuICAgIGlmKHBvdGVudGlhbFBhcmVudC5zdWJUeXBlcy5pbmRleE9mKG1vZGVsSWQpICE9PSAtMSl7XG4gICAgICBwYXJlbnQgPSBwb3RlbnRpYWxQYXJlbnQ7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH0pO1xuXG4gIGlmKCFwYXJlbnQpIHJldHVybjtcblxuICBmb3IodmFyIHByb3BlcnR5TmFtZSBpbiBwYXJlbnQucHJvcGVydGllcyl7XG4gICAgbW9kZWwucHJvcGVydGllc1twcm9wZXJ0eU5hbWVdID0gcGFyZW50LnByb3BlcnRpZXNbcHJvcGVydHlOYW1lXTtcbiAgfVxuICBcbiAgaWYocGFyZW50LnJlcXVpcmVkKSBtb2RlbC5yZXF1aXJlZCA9IG1vZGVsLnJlcXVpcmVkLmNvbmNhdChwYXJlbnQucmVxdWlyZWQpO1xuXG4gIGFkZEluaGVydGllZFByb3BlcnRpZXMobW9kZWwsIHBhcmVudC5pZCwgbW9kZWxzKTtcbn1cblxuZnVuY3Rpb24gdmFsaWRhdGVNb2RlbChjYW5kaWRhdGUsIG1vZGVsLCBtb2RlbHMpe1xuICBpZihjYW5kaWRhdGUgPT09IG51bGwgfHwgdHlwZW9mIGNhbmRpZGF0ZSAhPT0gJ29iamVjdCcpe1xuICAgIHJldHVybiBuZXcgVmFsaWRhdGlvbkVycm9ycyhjYW5kaWRhdGUsIG1vZGVsKTtcbiAgfVxuXG4gIG1vZGVscyA9IG1vZGVscyB8fCB7fTtcblxuICBtb2RlbCA9IGNsb25lKG1vZGVsKTtcbiAgaWYoIW1vZGVsLnJlcXVpcmVkKSBtb2RlbC5yZXF1aXJlZCA9IFtdO1xuICBhZGRJbmhlcnRpZWRQcm9wZXJ0aWVzKG1vZGVsLCBtb2RlbC5pZCwgbW9kZWxzKTtcblxuICB2YXIgZXJyb3JzID0gW107XG5cbiAgbW9kZWwucmVxdWlyZWQuZm9yRWFjaChmdW5jdGlvbihwcm9wZXJ0eU5hbWUpe1xuICAgIGlmIChjYW5kaWRhdGVbcHJvcGVydHlOYW1lXSAhPT0gdW5kZWZpbmVkKSByZXR1cm47XG5cbiAgICB2YXIgcHJvcGVydHkgPSBtb2RlbC5wcm9wZXJ0aWVzW3Byb3BlcnR5TmFtZV07XG4gICAgdmFyIGVycm9yID0gbmV3IE1pc3NpbmdWYWx1ZUVycm9yKCk7XG4gICAgZXJyb3JzLnB1c2gobmV3IFZhbGlkYXRpb25FcnJvcihwcm9wZXJ0eU5hbWUsIHByb3BlcnR5LCBlcnJvcikpO1xuICB9KTtcblxuICBPYmplY3Qua2V5cyhjYW5kaWRhdGUpLmZvckVhY2goZnVuY3Rpb24ocHJvcGVydHlOYW1lKXtcbiAgICB2YXIgcHJvcGVydHkgPSBtb2RlbC5wcm9wZXJ0aWVzW3Byb3BlcnR5TmFtZV07XG4gICAgXG4gICAgaWYocHJvcGVydHkgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gICAgdmFyIGVycm9yID0gdmFsaWRhdGUuZGF0YVR5cGUoY2FuZGlkYXRlW3Byb3BlcnR5TmFtZV0sIHByb3BlcnR5LCBtb2RlbHMpO1xuICAgIGlmKGVycm9yKXtcbiAgICAgIGVycm9ycy5wdXNoKG5ldyBWYWxpZGF0aW9uRXJyb3IocHJvcGVydHlOYW1lLCBwcm9wZXJ0eSwgZXJyb3IpKTtcbiAgICB9XG4gIH0pO1xuICBcbiAgaWYoZXJyb3JzLmxlbmd0aCl7XG4gICAgcmV0dXJuIG5ldyBWYWxpZGF0aW9uRXJyb3JzKGNhbmRpZGF0ZSwgbW9kZWwuaWQsIG1vZGVsLCBlcnJvcnMpO1xuICB9XG59XG5tb2R1bGUuZXhwb3J0cyA9IHZhbGlkYXRlTW9kZWw7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZXJyb3JUeXBlcyA9IHJlcXVpcmUoJy4vZXJyb3JUeXBlcycpLFxuICBWYWxpZGF0aW9uRXJyb3IgPSBlcnJvclR5cGVzLlZhbGlkYXRpb25FcnJvcixcbiAgVmFsaWRhdGlvbkVycm9ycyA9IGVycm9yVHlwZXMuVmFsaWRhdGlvbkVycm9ycyxcbiAgTWlzc2luZ1ZhbHVlRXJyb3IgPSBlcnJvclR5cGVzLk1pc3NpbmdWYWx1ZUVycm9yLFxuICB2YWxpZGF0ZSA9IHJlcXVpcmUoJy4vaW5kZXgnKTtcblxuZnVuY3Rpb24gdmFsaWRhdGVPcGVyYXRpb24oY2FuZGlkYXRlLCBvcGVyYXRpb24sIG1vZGVscyl7XG4gIHZhciBlcnJvcnMgPSBbXTtcbiAgXG4gIHZhciBwcmVzZW50UGFyYW1zID0gb3BlcmF0aW9uLnBhcmFtZXRlcnMuZmlsdGVyKGZ1bmN0aW9uKHBhcmFtKXtcbiAgICBpZiAoY2FuZGlkYXRlW3BhcmFtLm5hbWVdICE9PSB1bmRlZmluZWQpIHJldHVybiB0cnVlO1xuICAgIFxuICAgIGlmIChwYXJhbS5yZXF1aXJlZCkge1xuICAgICAgdmFyIGVycm9yID0gbmV3IE1pc3NpbmdWYWx1ZUVycm9yKCk7XG4gICAgICBlcnJvcnMucHVzaChuZXcgVmFsaWRhdGlvbkVycm9yKHBhcmFtLm5hbWUsIHBhcmFtLCBlcnJvcikpO1xuICAgIH1cblxuICAgIHJldHVybiBmYWxzZTtcbiAgfSk7XG5cbiAgcHJlc2VudFBhcmFtcy5mb3JFYWNoKGZ1bmN0aW9uKHBhcmFtKXtcbiAgICB2YXIgZXJyb3IgPSB2YWxpZGF0ZS5kYXRhVHlwZShjYW5kaWRhdGVbcGFyYW0ubmFtZV0sIHBhcmFtLCBtb2RlbHMpO1xuICAgIGlmKGVycm9yKXtcbiAgICAgIGVycm9ycy5wdXNoKG5ldyBWYWxpZGF0aW9uRXJyb3IocGFyYW0ubmFtZSwgcGFyYW0sIGVycm9yKSk7XG4gICAgfVxuICB9KTtcbiAgXG4gIGlmKGVycm9ycy5sZW5ndGgpe1xuICAgIHJldHVybiBuZXcgVmFsaWRhdGlvbkVycm9ycyhjYW5kaWRhdGUsIG9wZXJhdGlvbi5uaWNrbmFtZSwgb3BlcmF0aW9uLCBlcnJvcnMpO1xuICB9XG59XG5tb2R1bGUuZXhwb3J0cyA9IHZhbGlkYXRlT3BlcmF0aW9uOyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGVycm9yVHlwZXMgPSByZXF1aXJlKCcuL2Vycm9yVHlwZXMnKTtcblxuZnVuY3Rpb24gdmFsaWRhdGVJbnRlZ2VyKGNhbmRpZGF0ZSwgZGF0YVR5cGUpe1xuICB2YXIgZXJyb3IgPSB2YWxpZGF0ZU51bWJlcihjYW5kaWRhdGUsIGRhdGFUeXBlKTtcbiAgaWYoZXJyb3IpIHJldHVybiBlcnJvcjtcblxuICBpZihjYW5kaWRhdGUgJSAxKXtcbiAgICByZXR1cm4gbmV3IGVycm9yVHlwZXMuTm90QW5JbnRlZ2VyRXJyb3IoY2FuZGlkYXRlKTtcbiAgfVxufVxuZXhwb3J0cy52YWxpZGF0ZUludGVnZXIgPSB2YWxpZGF0ZUludGVnZXI7XG5cbmZ1bmN0aW9uIHZhbGlkYXRlTnVtYmVyKGNhbmRpZGF0ZSwgZGF0YVR5cGUpe1xuICBpZighKHR5cGVvZiBjYW5kaWRhdGUgPT09ICdudW1iZXInIHx8IGNhbmRpZGF0ZSBpbnN0YW5jZW9mIE51bWJlcikgfHwgaXNOYU4oY2FuZGlkYXRlKSl7XG4gICAgcmV0dXJuIG5ldyBlcnJvclR5cGVzLk5vdEFOdW1iZXJFcnJvcihjYW5kaWRhdGUsIHR5cGVvZiBjYW5kaWRhdGUpO1xuICB9XG4gIFxuICBpZigoZGF0YVR5cGUubWluaW11bSAhPT0gdW5kZWZpbmVkKSAmJiBjYW5kaWRhdGUgPCBwYXJzZUludChkYXRhVHlwZS5taW5pbXVtLCAxMCkpe1xuICAgIHJldHVybiBuZXcgZXJyb3JUeXBlcy5OdW1iZXJUb29TbWFsbEVycm9yKGNhbmRpZGF0ZSwgZGF0YVR5cGUubWluaW11bSk7XG4gIH1cbiAgXG4gIGlmKChkYXRhVHlwZS5tYXhpbXVtICE9PSB1bmRlZmluZWQpICYmIGNhbmRpZGF0ZSA+IHBhcnNlSW50KGRhdGFUeXBlLm1heGltdW0sIDEwKSl7XG4gICAgcmV0dXJuIG5ldyBlcnJvclR5cGVzLk51bWJlclRvb0xhcmdlRXJyb3IoY2FuZGlkYXRlLCBkYXRhVHlwZS5tYXhpbXVtKTtcbiAgfVxufVxuZXhwb3J0cy52YWxpZGF0ZU51bWJlciA9IHZhbGlkYXRlTnVtYmVyO1xuXG5mdW5jdGlvbiB2YWxpZGF0ZUJvb2xlYW4oY2FuZGlkYXRlKXtcbiAgaWYoISh0eXBlb2YgY2FuZGlkYXRlID09PSAnYm9vbGVhbicgfHwgY2FuZGlkYXRlIGluc3RhbmNlb2YgQm9vbGVhbikpe1xuICAgIHJldHVybiBuZXcgZXJyb3JUeXBlcy5Ob3RBQm9vbGVhbkVycm9yKGNhbmRpZGF0ZSwgdHlwZW9mIGNhbmRpZGF0ZSk7XG4gIH1cbn1cbmV4cG9ydHMudmFsaWRhdGVCb29sZWFuID0gdmFsaWRhdGVCb29sZWFuO1xuXG5cbmZ1bmN0aW9uIHZhbGlkYXRlVm9pZChjYW5kaWRhdGUpe1xuICBpZihjYW5kaWRhdGUgIT0gbnVsbCl7XG4gICAgcmV0dXJuIG5ldyBlcnJvclR5cGVzLk5vdFZvaWRFcnJvcihjYW5kaWRhdGUsIHR5cGVvZiBjYW5kaWRhdGUpO1xuICB9XG59XG5leHBvcnRzLnZhbGlkYXRlVm9pZCA9IHZhbGlkYXRlVm9pZDtcblxuZnVuY3Rpb24gdmFsaWRhdGVGaWxlKCl7XG4gIC8vIE5vdCBzdXJlIGhvdyB0byBjaGVjayB0aGlzLCBzaW5jZSBhbnl0aGluZyBjb3VsZCBxdWFsaWZ5IGFzICdGaWxlJy5cbn1cbmV4cG9ydHMudmFsaWRhdGVGaWxlID0gdmFsaWRhdGVGaWxlO1xuXG5mdW5jdGlvbiB2YWxpZGF0ZVN0cmluZyhjYW5kaWRhdGUsIGRhdGFUeXBlKXtcbiAgaWYodHlwZW9mIGNhbmRpZGF0ZSAhPT0gJ3N0cmluZycgJiYgIShjYW5kaWRhdGUgaW5zdGFuY2VvZiBTdHJpbmcpKXtcbiAgICByZXR1cm4gbmV3IGVycm9yVHlwZXMuTm90QVN0cmluZ0Vycm9yKGNhbmRpZGF0ZSwgdHlwZW9mIGNhbmRpZGF0ZSk7XG4gIH1cblxuICBpZignZW51bScgaW4gZGF0YVR5cGUpe1xuICAgIGlmKGRhdGFUeXBlLmVudW0uaW5kZXhPZihjYW5kaWRhdGUpID09PSAtMSkge1xuICAgICAgcmV0dXJuIG5ldyBlcnJvclR5cGVzLlN0cmluZ05vdEluRW51bUVycm9yKGNhbmRpZGF0ZSwgZGF0YVR5cGUuZW51bSk7XG4gICAgfVxuICB9XG59XG5leHBvcnRzLnZhbGlkYXRlU3RyaW5nID0gdmFsaWRhdGVTdHJpbmc7IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgTWlzc2luZ0F1dGhvcml6YXRpb25FcnJvciA9IHJlcXVpcmUoJy4vZXJyb3JUeXBlcycpLk1pc3NpbmdBdXRob3JpemF0aW9uRXJyb3I7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gYXBwbHlBdXRoRGF0YShvcGVyYXRpb24sIGF1dGhEYXRhLCByZXF1ZXN0KXtcbiAgdmFyIGF1dGhNYXAgPSBvcGVyYXRpb24uYXV0aG9yaXphdGlvbnM7XG4gIGlmKCFhdXRoTWFwKSBhdXRoTWFwID0gb3BlcmF0aW9uLmFwaU9iamVjdC5hcGlEZWNsYXJhdGlvbi5hdXRob3JpemF0aW9ucztcbiAgaWYoIWF1dGhNYXApIHJldHVybjtcblxuICB2YXIgYXV0aE5hbWVzID0gT2JqZWN0LmtleXMoYXV0aE1hcCkuZmlsdGVyKGZ1bmN0aW9uKGF1dGhOYW1lKXtcbiAgICAvLyBDdXJyZW50bHkgdW5hYmxlIHRvIGhhbmRsZSBvYXV0aDJcbiAgICByZXR1cm4gYXV0aE1hcFthdXRoTmFtZV0udHlwZSAhPT0gJ29hdXRoMic7XG4gIH0pO1xuXG4gIGlmKGF1dGhOYW1lcy5sZW5ndGggPT09IDApIHJldHVybjtcblxuICBpZihhdXRoTmFtZXMubGVuZ3RoID09PSAxKXtcbiAgICB2YXIgYXV0aE5hbWUgPSBhdXRoTmFtZXNbMF07XG4gICAgdmFyIGF1dGggPSBhdXRoTWFwW2F1dGhOYW1lXTtcblxuICAgIGlmKCFhdXRoRGF0YSkgdGhyb3cgbmV3IE1pc3NpbmdBdXRob3JpemF0aW9uRXJyb3IoYXV0aE5hbWUsIGF1dGgpO1xuXG4gICAgLy8gVW5wYWNrIG5lc3RlZCBhdXRoRGF0YSBmb3Igc2luZ2xlIGF1dGggb3BzOiB7IGFwaUtleTogJzEyMycgfSAtPiAnMTIzJ1xuICAgIGlmKGF1dGhEYXRhW2F1dGhOYW1lXSkgYXV0aERhdGEgPSBhdXRoRGF0YVthdXRoTmFtZV07XG5cbiAgICBpZihhdXRoLnR5cGUgPT09ICdhcGlLZXknKXtcbiAgICAgIGFwcGx5QXBpS2V5KGF1dGgsIGF1dGhOYW1lLCBhdXRoRGF0YSwgcmVxdWVzdCk7XG4gICAgfSBlbHNlIGlmKGF1dGgudHlwZSA9PT0gJ2Jhc2ljQXV0aCcpIHtcbiAgICAgIGFwcGx5QmFzaWNBdXRoKGF1dGgsIGF1dGhOYW1lLCBhdXRoRGF0YS51c2VybmFtZSwgYXV0aERhdGEucGFzc3dvcmQsIHJlcXVlc3QpO1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICB2YXIgaGFzQXV0aCA9IGF1dGhOYW1lcy5zb21lKGZ1bmN0aW9uKGF1dGhOYW1lKXtcbiAgICAgIHZhciBhdXRoID0gYXV0aE1hcFthdXRoTmFtZV07XG4gICAgICB2YXIgZGF0YSA9IGF1dGhEYXRhW2F1dGhOYW1lXTtcblxuICAgICAgaWYoIWRhdGEpIHJldHVybiBmYWxzZTtcblxuICAgICAgaWYoYXV0aC50eXBlID09PSAnYXBpS2V5Jyl7XG4gICAgICAgIGFwcGx5QXBpS2V5KGF1dGgsIGF1dGhOYW1lLCBkYXRhLCByZXF1ZXN0KTtcbiAgICAgIH0gZWxzZSBpZihhdXRoLnR5cGUgPT09ICdiYXNpY0F1dGgnKXtcbiAgICAgICAgYXBwbHlCYXNpY0F1dGgoYXV0aCwgYXV0aE5hbWUsIGRhdGEudXNlcm5hbWUsIGRhdGEucGFzc3dvcmQsIHJlcXVlc3QpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9KTtcblxuICAgIGlmKCFoYXNBdXRoKXtcbiAgICAgIHRocm93IG5ldyBNaXNzaW5nQXV0aG9yaXphdGlvbkVycm9yKGF1dGhOYW1lcy5qb2luKCcsICcpLCBhdXRoTWFwKTtcbiAgICB9XG4gIH1cbn07XG5cbmZ1bmN0aW9uIGFwcGx5QXBpS2V5KGF1dGgsIGF1dGhOYW1lLCBhcGlLZXksIHJlcXVlc3Qpe1xuICBpZighYXBpS2V5KSB0aHJvdyBuZXcgTWlzc2luZ0F1dGhvcml6YXRpb25FcnJvcihhdXRoTmFtZSwgYXV0aCk7XG4gIFxuICBpZihhdXRoLnBhc3NBcyA9PT0gJ2hlYWRlcicpe1xuICAgIHJlcXVlc3QuaGVhZGVyc1thdXRoLmtleW5hbWVdID0gYXBpS2V5O1xuICB9IGVsc2UgaWYoYXV0aC5wYXNzQXMgPT09ICdxdWVyeScpe1xuICAgIHZhciB1cmwgPSByZXF1ZXN0LnVybDtcbiAgICB2YXIgcXVlcnlQYXJhbSA9IGF1dGgua2V5bmFtZSArICc9JyArIGVuY29kZVVSSUNvbXBvbmVudChhcGlLZXkpO1xuICAgIGlmKHVybC5pbmRleE9mKCc/JykgPT09IC0xKXtcbiAgICAgIHVybCArPSAnPycgKyBxdWVyeVBhcmFtO1xuICAgIH0gZWxzZSB7XG4gICAgICB1cmwgPSB1cmwucmVwbGFjZSgnPycsICc/JyArIHF1ZXJ5UGFyYW0gKyAnJicpO1xuICAgIH1cblxuICAgIHJlcXVlc3QudXJsID0gdXJsO1xuICB9XG59XG5cbmZ1bmN0aW9uIGFwcGx5QmFzaWNBdXRoKGF1dGgsIGF1dGhOYW1lLCB1c2VybmFtZSwgcGFzc3dvcmQsIHJlcXVlc3Qpe1xuICBpZighdXNlcm5hbWUgfHwgIXBhc3N3b3JkKSB0aHJvdyBuZXcgTWlzc2luZ0F1dGhvcml6YXRpb25FcnJvcihhdXRoTmFtZSwgYXV0aCk7XG4gIFxuICB2YXIgdXJsID0gcmVxdWVzdC51cmw7XG4gIFxuICAvLyBPbmx5IGFkZCBiYXNpYyBhdXRoIG9uY2VcbiAgaWYodXJsLmluZGV4T2YoJ0AnKSA9PT0gLTEpe1xuICAgIHVybCA9IHVybC5yZXBsYWNlKCc6Ly8nLCAnOi8vJyArIHVzZXJuYW1lICsgJzonICsgcGFzc3dvcmQgKyAnQCcpO1xuICB9XG5cbiAgcmVxdWVzdC51cmwgPSB1cmw7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgY3JlYXRlT3BlcmF0aW9uSGFuZGxlciA9IHJlcXVpcmUoJy4vY3JlYXRlT3BlcmF0aW9uSGFuZGxlcicpO1xuXG5mdW5jdGlvbiBjcmVhdGVDbGllbnQoc2NoZW1hLCByZXF1ZXN0SGFuZGxlcil7XG4gIHZhciBhcGkgPSB7fSxcbiAgICBhcGlBdXRoRGF0YSxcbiAgICBhdXRoTWV0aG9kTmFtZSA9ICdhdXRoJztcblxuICBzY2hlbWEgPSBwcm9jZXNzU2NoZW1hKHNjaGVtYSk7XG4gIFxuICAvLyBJZiB0aGUgJ2F1dGgnIGtleSBpcyB1c2VkIGZvciBhbnkgcmVzb3VyY2Ugb3Igb3BlcmF0aW9uLCB3ZSdsbCB1c2VcbiAgLy8gJ2F1dGhvcml6YXRpb24nIGluc3RlYWQgZm9yIHRoZSBhdXRoIG1ldGhvZHNcbiAgdmFyIGF1dGhJc0luVXNlID0gc2NoZW1hLmFwaXMuc29tZShmdW5jdGlvbihyZXNvdXJjZU9iamVjdCl7XG4gICAgcmV0dXJuIHJlc291cmNlT2JqZWN0LmFwaURlY2xhcmF0aW9uLmFwaXMuc29tZShmdW5jdGlvbihhcGlPYmplY3Qpe1xuICAgICAgdmFyIHJlc291cmNlQXBpTmFtZSA9IGdldEFwaU5hbWUoYXBpT2JqZWN0LmFwaURlY2xhcmF0aW9uLnJlc291cmNlUGF0aCB8fCBhcGlPYmplY3QucGF0aCk7XG4gICAgICBpZihyZXNvdXJjZUFwaU5hbWUgPT09ICdhdXRoJykgcmV0dXJuIHRydWU7XG4gICAgICByZXR1cm4gYXBpT2JqZWN0Lm9wZXJhdGlvbnMuc29tZShmdW5jdGlvbihvcGVyYXRpb24pe1xuICAgICAgICByZXR1cm4gb3BlcmF0aW9uLm5pY2tuYW1lID09PSAnYXV0aCc7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG4gIFxuICBpZihhdXRoSXNJblVzZSkgYXV0aE1ldGhvZE5hbWUgPSAnYXV0aG9yaXphdGlvbic7XG5cbiAgYXBpW2F1dGhNZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCl7XG4gICAgYXBpQXV0aERhdGEgPSBwcm9jZXNzQXBpQXV0aEFyZ3MoYXJndW1lbnRzKTtcbiAgfTtcblxuICBzY2hlbWEuYXBpcy5mb3JFYWNoKGZ1bmN0aW9uKHJlc291cmNlT2JqZWN0KXtcbiAgICB2YXIgcmVzb3VyY2VOYW1lLFxuICAgICAgcmVzb3VyY2VBcGksXG4gICAgICByZXNvdXJjZUF1dGhEYXRhO1xuXG4gICAgaWYocmVzb3VyY2VPYmplY3QuYXBpRGVjbGFyYXRpb24ucmVzb3VyY2VQYXRoKXtcbiAgICAgIHJlc291cmNlTmFtZSA9IGdldEFwaU5hbWUocmVzb3VyY2VPYmplY3QuYXBpRGVjbGFyYXRpb24ucmVzb3VyY2VQYXRoKTtcbiAgICAgIHJlc291cmNlQXBpID0gYXBpW3Jlc291cmNlTmFtZV0gPSB7fTtcbiAgICAgIHJlc291cmNlQXBpW2F1dGhNZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCl7XG4gICAgICAgIHJlc291cmNlQXV0aERhdGEgPSBwcm9jZXNzQXBpQXV0aEFyZ3MoYXJndW1lbnRzKTtcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmVzb3VyY2VPYmplY3QuYXBpRGVjbGFyYXRpb24uYXBpcy5mb3JFYWNoKGZ1bmN0aW9uKGFwaU9iamVjdCl7XG4gICAgICB2YXIgYXBpT2JqZWN0TmFtZSA9IHJlc291cmNlTmFtZSxcbiAgICAgICAgYXBpT2JqZWN0QXBpID0gcmVzb3VyY2VBcGksXG4gICAgICAgIGFwaU9iamVjdEF1dGhEYXRhO1xuXG4gICAgICBpZighYXBpT2JqZWN0TmFtZSl7XG4gICAgICAgIGFwaU9iamVjdE5hbWUgPSBnZXRBcGlOYW1lKGFwaU9iamVjdC5wYXRoKTtcbiAgICAgICAgYXBpT2JqZWN0QXBpID0gYXBpW2FwaU9iamVjdE5hbWVdID0ge307XG4gICAgICAgIGFwaU9iamVjdEFwaVthdXRoTWV0aG9kTmFtZV0gPSBmdW5jdGlvbigpe1xuICAgICAgICAgIGFwaU9iamVjdEF1dGhEYXRhID0gcHJvY2Vzc0FwaUF1dGhBcmdzKGFyZ3VtZW50cyk7XG4gICAgICAgIH07XG4gICAgICB9XG5cbiAgICAgIGFwaU9iamVjdC5vcGVyYXRpb25zLmZvckVhY2goZnVuY3Rpb24ob3BlcmF0aW9uKXtcbiAgICAgICAgdmFyIG9wZXJhdGlvbkhhbmRsZXJOYW1lID0gb3BlcmF0aW9uLm5pY2tuYW1lLFxuICAgICAgICAgIG9wZXJhdGlvbkF1dGhEYXRhLFxuICAgICAgICAgIG9wZXJhdGlvbkhhbmRsZXI7IFxuICAgICAgICBcbiAgICAgICAgZnVuY3Rpb24gZ2V0QXV0aERhdGEoKXtcbiAgICAgICAgICByZXR1cm4gb3BlcmF0aW9uQXV0aERhdGEgfHwgYXBpT2JqZWN0QXV0aERhdGEgfHwgcmVzb3VyY2VBdXRoRGF0YSB8fCBhcGlBdXRoRGF0YTtcbiAgICAgICAgfVxuXG4gICAgICAgIG9wZXJhdGlvbkhhbmRsZXIgPSBjcmVhdGVPcGVyYXRpb25IYW5kbGVyKG9wZXJhdGlvbiwgZ2V0QXV0aERhdGEsIHJlcXVlc3RIYW5kbGVyKTtcblxuICAgICAgICBvcGVyYXRpb25IYW5kbGVyW2F1dGhNZXRob2ROYW1lXSA9IGZ1bmN0aW9uKCl7XG4gICAgICAgICAgb3BlcmF0aW9uQXV0aERhdGEgPSBwcm9jZXNzQXBpQXV0aEFyZ3MoYXJndW1lbnRzKTtcbiAgICAgICAgfTtcblxuICAgICAgICBhcGlPYmplY3RBcGlbb3BlcmF0aW9uSGFuZGxlck5hbWVdID0gb3BlcmF0aW9uSGFuZGxlcjtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9KTtcblxuICByZXR1cm4gYXBpO1xufVxubW9kdWxlLmV4cG9ydHMgPSBjcmVhdGVDbGllbnQ7XG5cbmZ1bmN0aW9uIHByb2Nlc3NBcGlBdXRoQXJncyhhcmdzKXtcbiAgLy8gZm9yIGJhc2ljIGF1dGgsIGFsbG93IGNhbGxzIHdpdGggdHdvIGFyZ3MgKHVzZXJuYW1lLCBwYXNzd29yZClcbiAgaWYodHlwZW9mIGFyZ3NbMF0gPT09ICdzdHJpbmcnICYmIHR5cGVvZiBhcmdzWzFdID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybiB7XG4gICAgICB1c2VybmFtZTogYXJnc1swXSxcbiAgICAgIHBhc3N3b3JkOiBhcmdzWzFdXG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gYXJnc1swXTtcbiAgfVxufVxuXG4vLyBIZWxwcGVyIG1ldGhvZCB3aGljaCBhc3NpbmdzIGJhY2sgcG9pbnRlciB0byBvYmplY3QgcGFyZW50cyBhbmQgcmV0dXJuc1xuLy8gdGhlIGFwaSBvYmplY3RzIHdpdGhpbiB0aGUgZ2l2ZW4gc2NoZW1hLlxuZnVuY3Rpb24gcHJvY2Vzc1NjaGVtYShzY2hlbWEpe1xuICBzY2hlbWEuYXBpcy5mb3JFYWNoKGZ1bmN0aW9uKHJlc291cmNlT2JqZWN0KXtcbiAgICByZXNvdXJjZU9iamVjdC5yZXNvdXJjZUxpc3RpbmcgPSBzY2hlbWE7XG5cbiAgICByZXNvdXJjZU9iamVjdC5hcGlEZWNsYXJhdGlvbi5hcGlzLmZvckVhY2goZnVuY3Rpb24oYXBpT2JqZWN0KXtcbiAgICAgIGFwaU9iamVjdC5yZXNvdXJjZU9iamVjdCA9IHJlc291cmNlT2JqZWN0O1xuICAgICAgYXBpT2JqZWN0LmFwaURlY2xhcmF0aW9uID0gcmVzb3VyY2VPYmplY3QuYXBpRGVjbGFyYXRpb247XG5cbiAgICAgIGFwaU9iamVjdC5vcGVyYXRpb25zLmZvckVhY2goZnVuY3Rpb24ob3BlcmF0aW9uKXtcbiAgICAgICAgb3BlcmF0aW9uLmFwaU9iamVjdCA9IGFwaU9iamVjdDtcblxuICAgICAgICBvcGVyYXRpb24ucGFyYW1ldGVycy5mb3JFYWNoKGZ1bmN0aW9uKHBhcmFtZXRlcil7XG4gICAgICAgICAgcGFyYW1ldGVyLm9wZXJhdGlvbiA9IG9wZXJhdGlvbjtcbiAgICAgICAgfSk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfSk7XG5cbiAgcmV0dXJuIHNjaGVtYTtcbn1cblxuLy8gVGFrZXMgYSBwYXRoIGFuZCByZXR1cm5zIGEgSmF2YVNjcmlwdC1mcmllbmRseSB2YXJpYWJsZSBuYW1lXG5mdW5jdGlvbiBnZXRBcGlOYW1lKG5hbWUpe1xuICAvLyBTdHJpbmcgbm9uLXdvcmQgY2hhcmFjdGVyc1xuICBuYW1lID0gbmFtZS5yZXBsYWNlKC9cXFcvZywgJy8nKTtcblxuICAvLyBUdXJuIHBhdGhzIHdoaWNoIGxvb2svbGlrZS90aGlzIHRvIGxvb2tMaWtlVGhpc1xuICBuYW1lID0gbmFtZS5yZXBsYWNlKC8oXFx3KVxcLyhcXHcpL2csIGZ1bmN0aW9uKG1hdGNoLCBwMSwgcDIpe1xuICAgIHJldHVybiBwMSArIHAyLnRvVXBwZXJDYXNlKCk7XG4gIH0pO1xuXG4gIG5hbWUgPSBuYW1lLnJlcGxhY2UoL1xcLy9nLCAnJyk7XG5cbiAgcmV0dXJuIG5hbWU7XG59IiwiJ3VzZSBzdHJpY3QnO1xuXG52YXIgZ2V0UmVxdWVzdEhlYWRlcnMgPSByZXF1aXJlKCcuL2dldFJlcXVlc3RIZWFkZXJzJyksXG4gIGdldFJlcXVlc3RVcmwgPSByZXF1aXJlKCcuL2dldFJlcXVlc3RVcmwnKSxcbiAgZ2V0UmVxdWVzdEJvZHkgPSByZXF1aXJlKCcuL2dldFJlcXVlc3RCb2R5JyksXG4gIGFwcGx5QXV0aERhdGEgPSByZXF1aXJlKCcuL2FwcGx5QXV0aERhdGEnKSxcbiAgZXJyb3JUeXBlcyA9IHJlcXVpcmUoJy4vZXJyb3JUeXBlcycpLFxuICBzd2FnZ2VyVmFsaWRhdGUgPSByZXF1aXJlKCdzd2FnZ2VyLXZhbGlkYXRlJyk7XG5cbnZhciBhbGxFcnJvclR5cGVzID0ge307XG5PYmplY3Qua2V5cyhzd2FnZ2VyVmFsaWRhdGUuZXJyb3JzKS5mb3JFYWNoKGZ1bmN0aW9uKGVycm9yTmFtZSl7XG4gIGFsbEVycm9yVHlwZXNbZXJyb3JOYW1lXSA9IHN3YWdnZXJWYWxpZGF0ZS5lcnJvcnNbZXJyb3JOYW1lXTtcbn0pO1xuXG5PYmplY3Qua2V5cyhlcnJvclR5cGVzKS5mb3JFYWNoKGZ1bmN0aW9uKGVycm9yTmFtZSl7XG4gIGFsbEVycm9yVHlwZXNbZXJyb3JOYW1lXSA9IGVycm9yVHlwZXNbZXJyb3JOYW1lXTtcbn0pO1xuXG5mdW5jdGlvbiBjcmVhdGVPcGVyYXRpb25IYW5kbGVyKG9wZXJhdGlvbiwgZ2V0QXV0aERhdGEsIHJlcXVlc3RIYW5kbGVyKXtcbiAgZnVuY3Rpb24gUmVxdWVzdChkYXRhLCBvcHRpb25zKXtcbiAgICB0aGlzLm1ldGhvZCA9IG9wZXJhdGlvbi5tZXRob2Q7XG4gICAgdGhpcy5vcGVyYXRpb24gPSBvcGVyYXRpb247XG4gICAgdGhpcy5lcnJvclR5cGVzID0gYWxsRXJyb3JUeXBlcztcbiAgICB0aGlzLmRhdGEgPSBkYXRhO1xuICAgIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gIH1cblxuICB2YXIgb3BlcmF0aW9uSGFuZGxlciA9IGZ1bmN0aW9uKGRhdGEsIG9wdGlvbnMpe1xuICAgIHZhciBlcnJvcixcbiAgICAgIHJlcXVlc3Q7XG4gICAgXG4gICAgb3B0aW9ucyA9IG9wdGlvbnMgfHwge307XG4gICAgXG4gICAgaWYoZGF0YSA9PSBudWxsKSBkYXRhID0ge307XG5cbiAgICAvLyBpZiBhIGZ1bmN0aW9uIGlzIHBhc3NlZCBpbiBhcyBvcHRpb25zLCBhc3N1bWUgaXQncyBhIGNhbGxiYWNrIGZ1bmN0aW9uXG4gICAgLy8gZm9yIGNvbnZlbmllbmNlXG4gICAgaWYodHlwZW9mIG9wdGlvbnMgPT09ICdmdW5jdGlvbicpe1xuICAgICAgb3B0aW9ucy5jYWxsYmFjayA9IG9wdGlvbnM7XG4gICAgfVxuXG4gICAgdHJ5e1xuICAgICAgZGF0YSA9IHBydW5lKGRhdGEpO1xuICAgICAgZGF0YSA9IHNpbmdsZVBhcmFtQ29udmVuaWVuY2VQcm9jZXNzb3Iob3BlcmF0aW9uLCBkYXRhKTtcbiAgICAgIGRhdGEgPSByZW1vdmVVbmtub3duUGFyYW1zKG9wZXJhdGlvbiwgZGF0YSk7XG5cbiAgICAgIGVycm9yID0gc3dhZ2dlclZhbGlkYXRlLm9wZXJhdGlvbihkYXRhLCBvcGVyYXRpb24sIG9wZXJhdGlvbi5hcGlPYmplY3QuYXBpRGVjbGFyYXRpb24ubW9kZWxzKTtcbiAgICAgIFxuICAgICAgcmVxdWVzdCA9IG5ldyBSZXF1ZXN0KGRhdGEsIG9wdGlvbnMpO1xuICAgICAgXG4gICAgICAvLyBJZiB3ZSBrbm93IHRoZXJlIGlzIGFuIGVycm9yLCBkb24ndCBhdHRlbXB0IHRvIGNyYWZ0IHRoZSByZXF1ZXN0IHBhcmFtcy5cbiAgICAgIC8vIFRoZSByZXF1ZXN0IHBhcmFtIGdlbmVyYXRvcnMgYXNzdW1lIHZhbGlkIGRhdGEgdG8gd29yayBwcm9wZXJseS5cbiAgICAgIGlmKCFlcnJvcil7XG4gICAgICAgIHJlcXVlc3QudXJsID0gZ2V0UmVxdWVzdFVybChvcGVyYXRpb24sIGRhdGEpO1xuICAgICAgICByZXF1ZXN0LmhlYWRlcnMgPSBnZXRSZXF1ZXN0SGVhZGVycyhvcGVyYXRpb24sIGRhdGEsIG9wdGlvbnMpO1xuICAgICAgICByZXF1ZXN0LmJvZHkgPSBnZXRSZXF1ZXN0Qm9keShvcGVyYXRpb24sIGRhdGEsIHJlcXVlc3QuaGVhZGVycyk7XG4gICAgICAgIFxuICAgICAgICBhcHBseUF1dGhEYXRhKG9wZXJhdGlvbiwgZ2V0QXV0aERhdGEoKSwgcmVxdWVzdCk7XG4gICAgICB9XG4gICAgfSBjYXRjaChlKXtcbiAgICAgIGVycm9yID0gZTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIHJlcXVlc3RIYW5kbGVyKGVycm9yLCByZXF1ZXN0KTtcbiAgfTtcblxuICAvLyBVc2VmdWwgZm9yIGluc3RhbmNlb2YgY2hlY2tzXG4gIG9wZXJhdGlvbkhhbmRsZXIuUmVxdWVzdCA9IFJlcXVlc3Q7XG4gIG9wZXJhdGlvbkhhbmRsZXIuZXJyb3JUeXBlcyA9IGFsbEVycm9yVHlwZXM7XG5cbiAgLy8gVXNlZnVsIGZvciByZWZsZWN0aW9uXG4gIG9wZXJhdGlvbkhhbmRsZXIub3BlcmF0aW9uID0gb3BlcmF0aW9uO1xuICBcbiAgLy8gQ2FuIGJlIHVzZWQgdG8gcHJlZW1wdGl2ZWx5IHZhbGlkYXRlIHdpdGhvdXQgYWN0aW9uXG4gIG9wZXJhdGlvbkhhbmRsZXIudmFsaWRhdGUgPSBmdW5jdGlvbihkYXRhKXtcbiAgICByZXR1cm4gc3dhZ2dlclZhbGlkYXRlLm9wZXJhdGlvbihkYXRhLCBvcGVyYXRpb24sIG9wZXJhdGlvbi5hcGlPYmplY3QuYXBpRGVjbGFyYXRpb24ubW9kZWxzKTtcbiAgfTtcblxuICByZXR1cm4gb3BlcmF0aW9uSGFuZGxlcjtcbn1cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlT3BlcmF0aW9uSGFuZGxlcjtcblxuZnVuY3Rpb24gbm9vcCgpe31cbmNyZWF0ZU9wZXJhdGlvbkhhbmRsZXIubG9nZ2VyID0ge1xuICBkZWJ1Zzogbm9vcCxcbiAgaW5mbzogbm9vcCxcbiAgd2Fybjogbm9vcCxcbiAgZXJyb3I6IG5vb3Bcbn07XG5cbi8vIFN0cmluZ2lmeSBhbmQgcGFyc2UgdGhlIGRhdGEgdG8gY2xlYW4gdXAgdW5kZWZpbmVkLCBhbmQgbm9uLXNjYWxhciBwcm9wZXJ0aWVzXG5mdW5jdGlvbiBwcnVuZShkYXRhKXtcbiAgcmV0dXJuIEpTT04ucGFyc2UoSlNPTi5zdHJpbmdpZnkoZGF0YSkpO1xufVxuXG4vLyBFbmFibGVzIGRhdGEgdG8gYmUgcGFzc2VkIGRpcmVjdGx5IGZvciBzaW5nbGUgcGFyYW0gb3BlcmF0aW9ucy5cbmZ1bmN0aW9uIHNpbmdsZVBhcmFtQ29udmVuaWVuY2VQcm9jZXNzb3Iob3BlcmF0aW9uLCBkYXRhKXtcbiAgLy8gSWYgdGhlcmUgYXJlIG1vcmUgdGhhbiBvbmUgcGFyYW1zLCBiYWlsXG4gIHZhciByZXF1aXJlZFBhcmFtcyA9IG9wZXJhdGlvbi5wYXJhbWV0ZXJzLmZpbHRlcihmdW5jdGlvbihwYXJhbSl7XG4gICAgcmV0dXJuIHBhcmFtLnJlcXVpcmVkO1xuICB9KTtcblxuICAvLyBJZiB0aGVyZSBhcmUgbW9yZSB0aGFuIG9uZSByZXF1aXJlZCBwYXJhbXMsIG9yIGlmIHRoZXJlIGlzIG5vIHJlcXVpcmVkIHBhcmFtXG4gIC8vIGFuZCB0aGVyZSBhcmUgbWFueSBvcHRpb25hbCBwYXJhbXMsIGJhaWxcbiAgaWYocmVxdWlyZWRQYXJhbXMubGVuZ3RoID4gMSkgcmV0dXJuIGRhdGE7XG5cbiAgaWYocmVxdWlyZWRQYXJhbXMubGVuZ3RoICE9PSAxICYmIG9wZXJhdGlvbi5wYXJhbWV0ZXJzLmxlbmd0aCAhPT0gMSkgcmV0dXJuIGRhdGE7XG5cbiAgdmFyIHBhcmFtID0gcmVxdWlyZWRQYXJhbXNbMF0gfHwgb3BlcmF0aW9uLnBhcmFtZXRlcnNbMF07XG4gIFxuICAvLyBJZiB0aGUgcGFyYW0gaXMgYWxyZWFkeSBkZWZpbmVkIGV4cGxpY2l0bHksIGJhaWxcbiAgaWYodHlwZW9mIGRhdGEgPT09ICdvYmplY3QnICYmICBkYXRhW3BhcmFtLm5hbWVdICE9PSB1bmRlZmluZWQpIHJldHVybiBkYXRhO1xuXG4gIHZhciBtb2RlbHMgPSBvcGVyYXRpb24uYXBpT2JqZWN0LmFwaURlY2xhcmF0aW9uLm1vZGVscztcblxuICAvLyBJZiB0aGUgZGF0YSBwYXNzZWQgaXMgaXMgbm90IHZhbGlkIGZvciB0aGUgcGFyYW0gZGF0YSB0eXBlLCBiYWlsXG4gIHZhciBlcnJvcjtcblxuICB0cnkge1xuICAgIGVycm9yID0gc3dhZ2dlclZhbGlkYXRlLmRhdGFUeXBlKGRhdGEsIHBhcmFtLCBtb2RlbHMpOyBcbiAgfSBjYXRjaChlKXtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxuICBcbiAgLy8gSWYgdGhlIGRhdGEgcGFzc2VkIGlzIGEgdmFsaWQgcGFyYW0gZGF0YSB0eXBlLCBiYWlsXG4gIGlmKCFlcnJvcil7XG4gICAgdmFyIHdyYXBwZXIgPSB7fTtcbiAgICB3cmFwcGVyW3BhcmFtLm5hbWVdID0gZGF0YTtcbiAgICByZXR1cm4gd3JhcHBlcjtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZGF0YTtcbiAgfVxufVxuIFxuXG5mdW5jdGlvbiByZW1vdmVVbmtub3duUGFyYW1zKG9wZXJhdGlvbiwgZGF0YSl7XG4gIGlmKCFkYXRhIHx8IHR5cGVvZiBkYXRhICE9PSAnb2JqZWN0JykgcmV0dXJuIGRhdGE7XG5cbiAgdmFyIHBhcmFtTmFtZXMgPSB7fTtcbiAgb3BlcmF0aW9uLnBhcmFtZXRlcnMuZm9yRWFjaChmdW5jdGlvbihwYXJhbSl7XG4gICAgcGFyYW1OYW1lc1twYXJhbS5uYW1lXSA9IHRydWU7XG4gIH0pO1xuXG4gIHZhciB1bmtub3duS2V5cyA9IE9iamVjdC5rZXlzKGRhdGEpLmZpbHRlcihmdW5jdGlvbihrZXkpe1xuICAgIHJldHVybiAhKGtleSBpbiBwYXJhbU5hbWVzKTtcbiAgfSk7XG5cbiAgY3JlYXRlT3BlcmF0aW9uSGFuZGxlci5sb2dnZXIud2FybignVW5rbm93biBwYXJhbWV0ZXJzIHJlbW92ZWQgZnJvbSByZXF1ZXN0OicsIFxuICAgIHVua25vd25LZXlzLmpvaW4oJywgJykpO1xuXG4gIHVua25vd25LZXlzLmZvckVhY2goZnVuY3Rpb24oa2V5KXtcbiAgICBkZWxldGUgZGF0YVtrZXldO1xuICB9KTtcblxuICByZXR1cm4gZGF0YTtcbn0iLCIndXNlIHN0cmljdCc7XG5cbmZ1bmN0aW9uIEludmFsaWRSZXF1ZXN0RXJyb3IobWVzc2FnZSl7XG4gIHRoaXMubmFtZSA9ICdJbnZhbGlkUmVxdWVzdEVycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZSB8fCAnSW52YWxpZCByZXF1ZXN0Jztcbn1cbkludmFsaWRSZXF1ZXN0RXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpO1xuSW52YWxpZFJlcXVlc3RFcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBJbnZhbGlkUmVxdWVzdEVycm9yO1xuXG5leHBvcnRzLkludmFsaWRSZXF1ZXN0RXJyb3IgPSBJbnZhbGlkUmVxdWVzdEVycm9yO1xuXG5cbmZ1bmN0aW9uIE1pc3NpbmdBdXRob3JpemF0aW9uRXJyb3IoYXV0aE5hbWUsIGF1dGgpe1xuICB0aGlzLm5hbWUgPSAnTWlzc2luZ0F1dGhvcml6YXRpb25FcnJvcic7XG4gIHRoaXMubWVzc2FnZSA9ICdObyBkYXRhIGZvdW5kIGZvciBhdXRob3JpemF0aW9uOiAnICsgYXV0aE5hbWU7XG4gIHRoaXMuYXV0aG9yaXphdGlvbiA9IGF1dGg7XG59XG5NaXNzaW5nQXV0aG9yaXphdGlvbkVycm9yLnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoSW52YWxpZFJlcXVlc3RFcnJvci5wcm90b3R5cGUpO1xuTWlzc2luZ0F1dGhvcml6YXRpb25FcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBNaXNzaW5nQXV0aG9yaXphdGlvbkVycm9yO1xuXG5leHBvcnRzLk1pc3NpbmdBdXRob3JpemF0aW9uRXJyb3IgPSBNaXNzaW5nQXV0aG9yaXphdGlvbkVycm9yO1xuXG5cbmZ1bmN0aW9uIE1pc3NpbmdQYXRoUGFyYW1zRXJyb3IocGF0aFBhcmFtcyl7XG4gIHRoaXMubmFtZSA9ICdNaXNzaW5nUGF0aFBhcmFtc0Vycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gJ01pc3NpbmcgdGhlIGZvbGxvd2luZyByZXF1aXJlZCBwYXRoIHBhcmFtZXRlcnM6ICcgKyBwYXRoUGFyYW1zLmpvaW4oJycpO1xufVxuTWlzc2luZ1BhdGhQYXJhbXNFcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEludmFsaWRSZXF1ZXN0RXJyb3IucHJvdG90eXBlKTtcbk1pc3NpbmdQYXRoUGFyYW1zRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gTWlzc2luZ1BhdGhQYXJhbXNFcnJvcjtcblxuZXhwb3J0cy5NaXNzaW5nUGF0aFBhcmFtc0Vycm9yID0gTWlzc2luZ1BhdGhQYXJhbXNFcnJvcjtcblxuXG5mdW5jdGlvbiBDb250ZW50VHlwZU5vdFN1cHBvcnRlZEVycm9yKGNvbnRlbnRUeXBlLCBvcGVyYXRpb24pe1xuICB2YXIgYXBpRGVjbGFyYXRpb24gPSBvcGVyYXRpb24uYXBpT2JqZWN0LmFwaURlY2xhcmF0aW9uO1xuICB2YXIgY29uc3VtZXMgPSBvcGVyYXRpb24uY29uc3VtZXMgfHwgYXBpRGVjbGFyYXRpb24uY29uc3VtZXMgfHwgW107XG5cbiAgdGhpcy5uYW1lID0gJ0NvbnRlbnRUeXBlTm90U3VwcG9ydGVkRXJyb3InO1xuICB0aGlzLm1lc3NhZ2UgPSAnT3BlcmF0aW9uIFsnICsgb3BlcmF0aW9uLm5pY2tuYW1lICsgJ10gZG9lcyBub3QgYWNjZXB0ICcgKyBjb250ZW50VHlwZSArICcuIEl0IHN1cHBvcnRzOiAnICsgXG4gICAgY29uc3VtZXMuam9pbignLCAnKTtcbn1cbkNvbnRlbnRUeXBlTm90U3VwcG9ydGVkRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShJbnZhbGlkUmVxdWVzdEVycm9yLnByb3RvdHlwZSk7XG5Db250ZW50VHlwZU5vdFN1cHBvcnRlZEVycm9yLnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IENvbnRlbnRUeXBlTm90U3VwcG9ydGVkRXJyb3I7XG5cbmV4cG9ydHMuQ29udGVudFR5cGVOb3RTdXBwb3J0ZWRFcnJvciA9IENvbnRlbnRUeXBlTm90U3VwcG9ydGVkRXJyb3I7XG5cblxuZnVuY3Rpb24gQWNjZXB0c05vdFN1cHBvcnRlZEVycm9yKGFjY2VwdHMsIG9wZXJhdGlvbil7XG4gIHZhciBhcGlEZWNsYXJhdGlvbiA9IG9wZXJhdGlvbi5hcGlPYmplY3QuYXBpRGVjbGFyYXRpb247XG4gIHZhciBwcm9kdWNlcyA9IG9wZXJhdGlvbi5wcm9kdWNlcyB8fCBhcGlEZWNsYXJhdGlvbi5wcm9kdWNlcyB8fCBbXTtcblxuICB0aGlzLm5hbWUgPSAnQWNjZXB0c05vdFN1cHBvcnRlZEVycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gJ09wZXJhdGlvbiBbJyArIG9wZXJhdGlvbi5uaWNrbmFtZSArICddIGRvZXMgbm90IHByb2R1Y2UgJyArIGFjY2VwdHMgKyAnLiBJdCBzdXBwb3J0czogJyArIFxuICAgIHByb2R1Y2VzLmpvaW4oJywgJyk7XG59XG5BY2NlcHRzTm90U3VwcG9ydGVkRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShJbnZhbGlkUmVxdWVzdEVycm9yLnByb3RvdHlwZSk7XG5BY2NlcHRzTm90U3VwcG9ydGVkRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQWNjZXB0c05vdFN1cHBvcnRlZEVycm9yO1xuXG5leHBvcnRzLkFjY2VwdHNOb3RTdXBwb3J0ZWRFcnJvciA9IEFjY2VwdHNOb3RTdXBwb3J0ZWRFcnJvcjtcblxuXG5mdW5jdGlvbiBPcGVyYXRpb25WYWxpZGF0aW9uRXJyb3Iob3BlcmF0aW9uLCBlcnJvcnMpe1xuICB0aGlzLm5hbWUgPSAnT3BlcmF0aW9uVmFsaWRhdGlvbkVycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gb3BlcmF0aW9uLm5pY2tuYW1lICsgJyBmYWlsZWQgdmFsaWRhdGlvbjogXFxuXFx0JyArIGVycm9ycy5qb2luKCdcXG5cXHQnKTtcbn1cbk9wZXJhdGlvblZhbGlkYXRpb25FcnJvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEludmFsaWRSZXF1ZXN0RXJyb3IucHJvdG90eXBlKTtcbk9wZXJhdGlvblZhbGlkYXRpb25FcnJvci5wcm90b3R5cGUuY29uc3RydWN0b3IgPSBPcGVyYXRpb25WYWxpZGF0aW9uRXJyb3I7XG5cbmV4cG9ydHMuT3BlcmF0aW9uVmFsaWRhdGlvbkVycm9yID0gT3BlcmF0aW9uVmFsaWRhdGlvbkVycm9yO1xuXG5cbmZ1bmN0aW9uIFBhcmFtZXRlclZhbGlkYXRpb25FcnJvcihwYXJhbWV0ZXIsIGVycm9ycyl7XG4gIHRoaXMubmFtZSA9ICdQYXJhbWV0ZXJWYWxpZGF0aW9uRXJyb3InO1xuICB0aGlzLm1lc3NhZ2UgPSBwYXJhbWV0ZXIubmFtZSArICcgZmFpbGVkIHZhbGlkYXRpb246IFxcblxcdCcgKyBlcnJvcnMuam9pbignXFxuXFx0Jyk7XG59XG5QYXJhbWV0ZXJWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShJbnZhbGlkUmVxdWVzdEVycm9yLnByb3RvdHlwZSk7XG5QYXJhbWV0ZXJWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gUGFyYW1ldGVyVmFsaWRhdGlvbkVycm9yO1xuXG5leHBvcnRzLlBhcmFtZXRlclZhbGlkYXRpb25FcnJvciA9IFBhcmFtZXRlclZhbGlkYXRpb25FcnJvcjtcblxuXG5mdW5jdGlvbiBEYXRhVHlwZVZhbGlkYXRpb25FcnJvcihtZXNzYWdlKXtcbiAgdGhpcy5uYW1lID0gJ0RhdGFUeXBlVmFsaWRhdGlvbkVycm9yJztcbiAgdGhpcy5tZXNzYWdlID0gbWVzc2FnZSB8fCAnSW52YWxpZCBkYXRhIHR5cGUnO1xufVxuRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShFcnJvci5wcm90b3R5cGUpO1xuRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3I7XG5cbmV4cG9ydHMuRGF0YVR5cGVWYWxpZGF0aW9uRXJyb3IgPSBEYXRhVHlwZVZhbGlkYXRpb25FcnJvcjsiLCIndXNlIHN0cmljdCc7XG5cbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0UmVxdWVzdEJvZHkob3BlcmF0aW9uLCBkYXRhLCBoZWFkZXJzKXtcbiAgdmFyIGJvZHkgPSBvcGVyYXRpb24ucGFyYW1ldGVycy5maWx0ZXIoZnVuY3Rpb24ocGFyYW0pe1xuICAgIHJldHVybiBwYXJhbS5wYXJhbVR5cGUgPT09ICdib2R5JyAmJiBkYXRhW3BhcmFtLm5hbWVdICE9IG51bGw7XG4gIH0pLm1hcChmdW5jdGlvbihwYXJhbSl7XG4gICAgcmV0dXJuIGRhdGFbcGFyYW0ubmFtZV07XG4gIH0pWzBdO1xuXG4gIGlmKCEoaGVhZGVycyAmJiAgaGVhZGVyc1snQ29udGVudC1UeXBlJ10pKSByZXR1cm4gYm9keTtcblxuICB2YXIgY29udGVudFR5cGUgPSBoZWFkZXJzWydDb250ZW50LVR5cGUnXTtcbiAgdmFyIHByZXNlbnRGb3JtUGFyYW1zID0gb3BlcmF0aW9uLnBhcmFtZXRlcnMuZmlsdGVyKGZ1bmN0aW9uKHBhcmFtKXtcbiAgICByZXR1cm4gcGFyYW0ucGFyYW1UeXBlID09PSAnZm9ybScgJiYgZGF0YVtwYXJhbS5uYW1lXSAhPSBudWxsO1xuICB9KTtcblxuICBpZihjb250ZW50VHlwZS5pbmRleE9mKCdhcHBsaWNhdGlvbi94LXd3dy1mb3JtLXVybGVuY29kZWQnKSAhPT0gLTEpe1xuICAgIGJvZHkgPSBwcmVzZW50Rm9ybVBhcmFtcy5tYXAoZnVuY3Rpb24ocGFyYW0pe1xuICAgICAgdmFyIGtleSA9IHBhcmFtLm5hbWUsXG4gICAgICAgIHZhbHVlID0gZGF0YVtrZXldO1xuICAgICAgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChrZXkpICsgJz0nICsgZW5jb2RlVVJJQ29tcG9uZW50KHZhbHVlKTtcbiAgICB9KS5qb2luKCcmJyk7XG4gIH0gZWxzZSBpZihjb250ZW50VHlwZS5pbmRleE9mKCdtdWx0aXBhcnQvZm9ybS1kYXRhJykgIT09IC0xKXtcbiAgICB2YXIgcmFuZG9tbmVzcyA9IE1hdGgucmFuZG9tKCkudG9TdHJpbmcoMTYpLnN1YnN0cigyKTtcbiAgICB2YXIgYm91bmRhcnkgPSAnU3dhZ2dlckJvdW5kYXJ5JyArIHJhbmRvbW5lc3M7XG4gICAgXG4gICAgYm9keSA9IHByZXNlbnRGb3JtUGFyYW1zLm1hcChmdW5jdGlvbihwYXJhbSl7XG4gICAgICB2YXIga2V5ID0gcGFyYW0ubmFtZSxcbiAgICAgICAgdmFsdWUgPSBkYXRhW2tleV0sXG4gICAgICAgIHJlc3VsdCA9ICctLScgKyBib3VuZGFyeTtcblxuICAgICAgcmVzdWx0ICs9ICdcXG5Db250ZW50LURpc3Bvc2l0aW9uOiBmb3JtLWRhdGE7IG5hbWU9XCInICsga2V5ICsgJ1wiJztcbiAgICAgIFxuICAgICAgaWYodmFsdWUuY29udGVudFR5cGUpe1xuICAgICAgICBpZih2YWx1ZS5uYW1lKXtcbiAgICAgICAgICByZXN1bHQgKz0gJzsgZmlsZW5hbWU9XCInICsgdmFsdWUubmFtZSArICdcIic7XG4gICAgICAgIH1cblxuICAgICAgICByZXN1bHQgKz0gJ1xcbkNvbnRlbnQtVHlwZTogJyArIHZhbHVlLmNvbnRlbnRUeXBlO1xuICAgICAgfVxuXG4gICAgICBpZih2YWx1ZS5jb250ZW50VHJhbnNmZXJFbmNvZGluZyl7XG4gICAgICAgIHJlc3VsdCArPSAnXFxuQ29udGVudC1UcmFuc2Zlci1FbmNvZGluZzogJyArIHZhbHVlLmNvbnRlbnRUcmFuc2ZlckVuY29kaW5nO1xuICAgICAgfVxuXG4gICAgICBpZih2YWx1ZS5ib2R5KXtcbiAgICAgICAgcmVzdWx0ICs9ICdcXG5cXG4nICsgdmFsdWUuYm9keTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJlc3VsdCArPSAnXFxuXFxuJyArIHZhbHVlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH0pLmpvaW4oJ1xcbicpO1xuXG4gICAgYm9keSArPSAnXFxuLS0nICsgYm91bmRhcnkgKyAnLS1cXG4nO1xuICAgIFxuICAgIGhlYWRlcnNbJ0NvbnRlbnQtVHlwZSddID0gY29udGVudFR5cGUucmVwbGFjZShcbiAgICAgICdtdWx0aXBhcnQvZm9ybS1kYXRhJywgXG4gICAgICAnbXVsdGlwYXJ0L2Zvcm0tZGF0YTsgYm91bmRhcnk9JyArIGJvdW5kYXJ5XG4gICAgKTtcbiAgfSBlbHNlIGlmKGNvbnRlbnRUeXBlLmluZGV4T2YoJ2FwcGxpY2F0aW9uL2pzb24nKSAhPT0gLTEpe1xuICAgIGlmKHR5cGVvZiBib2R5ICE9PSAnc3RyaW5nJyl7XG4gICAgICBib2R5ID0gSlNPTi5zdHJpbmdpZnkoYm9keSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGJvZHk7XG59OyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGVycm9yVHlwZXMgPSByZXF1aXJlKCcuL2Vycm9yVHlwZXMnKSxcbiAgQ29udGVudFR5cGVOb3RTdXBwb3J0ZWRFcnJvciA9IGVycm9yVHlwZXMuQ29udGVudFR5cGVOb3RTdXBwb3J0ZWRFcnJvcixcbiAgQWNjZXB0c05vdFN1cHBvcnRlZEVycm9yID0gZXJyb3JUeXBlcy5BY2NlcHRzTm90U3VwcG9ydGVkRXJyb3I7XG5cbnZhciBERUZBVUxUX0FDQ0VQVCA9ICdhcHBsaWNhdGlvbi9qc29uJztcbm1vZHVsZS5leHBvcnRzID0gZnVuY3Rpb24gZ2V0UmVxdWVzdEhlYWRlcnMob3BlcmF0aW9uLCBkYXRhLCBvcHRpb25zKXtcbiAgZGF0YSA9IGRhdGEgfHwge307XG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBoZWFkZXJzID0ge307XG5cbiAgb3BlcmF0aW9uLnBhcmFtZXRlcnMuZm9yRWFjaChmdW5jdGlvbihwYXJhbSl7XG4gICAgaWYocGFyYW0ucGFyYW1UeXBlID09PSAnaGVhZGVyJyAmJiBkYXRhW3BhcmFtLm5hbWVdICE9IG51bGwpe1xuICAgICAgaGVhZGVyc1twYXJhbS5uYW1lXSA9IGRhdGFbcGFyYW0ubmFtZV07XG4gICAgfVxuICB9KTtcblxuICAvLyBQYXNzZWQgaGVhZGVyc1xuICBpZihvcHRpb25zLmhlYWRlcnMpe1xuICAgIE9iamVjdC5rZXlzKG9wdGlvbnMuaGVhZGVycykuZm9yRWFjaChmdW5jdGlvbihrZXkpe1xuICAgICAgaGVhZGVyc1trZXldID0gb3B0aW9ucy5oZWFkZXJzW2tleV07XG4gICAgfSk7XG4gIH1cblxuICAvLyBDb250ZW50LVR5cGVcbiAgdmFyIGNvbnRlbnRUeXBlID0gb3B0aW9ucy5jb250ZW50VHlwZSB8fCBnZXRDb250ZW50VHlwZShvcGVyYXRpb24sIGRhdGEsIG9wdGlvbnMpO1xuICBpZihjb250ZW50VHlwZSkge1xuICAgIGlmKGhhc0FjY2VwdChvcGVyYXRpb24sIGNvbnRlbnRUeXBlKSl7XG4gICAgICBoZWFkZXJzWydDb250ZW50LVR5cGUnXSA9IGNvbnRlbnRUeXBlOyAgXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBDb250ZW50VHlwZU5vdFN1cHBvcnRlZEVycm9yKGNvbnRlbnRUeXBlLCBvcGVyYXRpb24pO1xuICAgIH1cbiAgfVxuXG4gIC8vIEFjY2VwdFxuICB2YXIgYWNjZXB0ID0gb3B0aW9ucy5hY2NlcHQgfHwgREVGQVVMVF9BQ0NFUFQ7XG4gIGlmKGFjY2VwdCl7XG4gICAgaWYoaGFzQ29udGVudFR5cGUob3BlcmF0aW9uLCBhY2NlcHQpKXtcbiAgICAgIGhlYWRlcnMuQWNjZXB0ID0gYWNjZXB0OyAgXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBBY2NlcHRzTm90U3VwcG9ydGVkRXJyb3IoYWNjZXB0LCBvcGVyYXRpb24pO1xuICAgIH1cbiAgfVxuICBcbiAgcmV0dXJuIGhlYWRlcnM7XG59O1xuXG5mdW5jdGlvbiBnZXRDb250ZW50VHlwZShvcGVyYXRpb24sIGRhdGEpe1xuICB2YXIgaGFzQm9keSA9IG9wZXJhdGlvbi5wYXJhbWV0ZXJzLnNvbWUoZnVuY3Rpb24ocGFyYW0pe1xuICAgIHJldHVybiBwYXJhbS5wYXJhbVR5cGUgPT09ICdib2R5JyAmJiBkYXRhW3BhcmFtLm5hbWVdICE9PSB1bmRlZmluZWQ7XG4gIH0pO1xuXG4gIGlmIChoYXNCb2R5KXtcbiAgICByZXR1cm4gJ2FwcGxpY2F0aW9uL2pzb24nO1xuICB9IGVsc2Uge1xuICAgIHZhciBoYXNGb3JtUGFyYW1zID0gb3BlcmF0aW9uLnBhcmFtZXRlcnMuc29tZShmdW5jdGlvbihwYXJhbSl7XG4gICAgICByZXR1cm4gcGFyYW0ucGFyYW1UeXBlID09PSAnZm9ybScgJiYgZGF0YVtwYXJhbS5uYW1lXSAhPT0gdW5kZWZpbmVkO1xuICAgIH0pO1xuXG4gICAgdmFyIGhhc0ZpbGVQYXJhbSA9IGhhc0Zvcm1QYXJhbXMgJiYgXG4gICAgICBvcGVyYXRpb24ucGFyYW1ldGVycy5zb21lKGZ1bmN0aW9uKHBhcmFtKXtcbiAgICAgICAgcmV0dXJuIHBhcmFtLnR5cGUgPT09ICdGaWxlJyAmJiBkYXRhW3BhcmFtLm5hbWVdICE9PSB1bmRlZmluZWQ7XG4gICAgICB9KTtcblxuICAgIGlmKGhhc0ZpbGVQYXJhbSkgcmV0dXJuICdtdWx0aXBhcnQvZm9ybS1kYXRhJztcbiAgICBlbHNlIGlmKGhhc0Zvcm1QYXJhbXMpIHJldHVybiAnYXBwbGljYXRpb24veC13d3ctZm9ybS11cmxlbmNvZGVkJztcbiAgfVxufVxuXG4vLyBBY2NlcHRzIGlzIGFuIG9wdGlvbmFsIGZpZWxkIGluIHRoZSBzcGVjLCBidXQgbXVzdCBiZSBlbmZvcmNlZCB3aGVuIHByZXNlbnRcbmZ1bmN0aW9uIGhhc0FjY2VwdChvcGVyYXRpb24sIGNvbnRlbnRUeXBlKXtcbiAgdmFyIGFwaURlY2xhcmF0aW9uID0gb3BlcmF0aW9uLmFwaU9iamVjdC5hcGlEZWNsYXJhdGlvbjtcbiAgdmFyIGFjY2VwdHMgPSBvcGVyYXRpb24uY29uc3VtZXMgfHwgYXBpRGVjbGFyYXRpb24uY29uc3VtZXM7XG5cbiAgaWYoYWNjZXB0cyAmJiBhY2NlcHRzLmxlbmd0aCl7XG4gICAgcmV0dXJuIGFjY2VwdHMuaW5kZXhPZihjb250ZW50VHlwZSkgIT09IC0xO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG59XG5leHBvcnRzLmhhc0FjY2VwdCA9IGhhc0FjY2VwdDtcblxuLy8gQ29udGVudC1UeXBlIChwcm9kdWNlcykgaXMgYW4gb3B0aW9uYWwgZmllbGQgaW4gdGhlIHNwZWMsIGJ1dCBtdXN0IGJlIGVuZm9yY2VkIHdoZW4gcHJlc2VudFxuZnVuY3Rpb24gaGFzQ29udGVudFR5cGUob3BlcmF0aW9uLCBjb250ZW50VHlwZSl7XG4gIHZhciBhcGlEZWNsYXJhdGlvbiA9IG9wZXJhdGlvbi5hcGlPYmplY3QuYXBpRGVjbGFyYXRpb24sXG4gICAgY29udGVudFR5cGVzID0gb3BlcmF0aW9uLnByb2R1Y2VzIHx8IGFwaURlY2xhcmF0aW9uLnByb2R1Y2VzO1xuXG4gIGlmKGNvbnRlbnRUeXBlcyAmJiBjb250ZW50VHlwZXMubGVuZ3RoKXtcbiAgICByZXR1cm4gY29udGVudFR5cGVzLmluZGV4T2YoY29udGVudFR5cGUpICE9PSAtMTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxufVxuZXhwb3J0cy5oYXNDb250ZW50VHlwZSA9IGhhc0NvbnRlbnRUeXBlOyIsIid1c2Ugc3RyaWN0JztcblxudmFyIGVycm9yVHlwZXMgPSByZXF1aXJlKCcuL2Vycm9yVHlwZXMnKSxcbiAgTWlzc2luZ1BhdGhQYXJhbXNFcnJvciA9IGVycm9yVHlwZXMuTWlzc2luZ1BhdGhQYXJhbXNFcnJvcjtcblxubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBnZXRSZXF1ZXN0VXJsKG9wZXJhdGlvbiwgZGF0YSl7XG4gIHZhciB1cmwgPSBnZXRVcmxUZW1wbGF0ZShvcGVyYXRpb24pO1xuXG4gIHVybCA9IGFwcGx5UGF0aFBhcmFtcyh1cmwsIG9wZXJhdGlvbiwgZGF0YSk7XG5cbiAgaWYoIWRhdGEpIHJldHVybiB1cmw7XG5cbiAgdmFyIHF1ZXJ5UGFyYW1zID0gb3BlcmF0aW9uLnBhcmFtZXRlcnMuZmlsdGVyKGZ1bmN0aW9uKHBhcmFtKXtcbiAgICByZXR1cm4gcGFyYW0ucGFyYW1UeXBlID09PSAncXVlcnknICYmIGRhdGFbcGFyYW0ubmFtZV0gIT09IHVuZGVmaW5lZDtcbiAgfSkubWFwKGZ1bmN0aW9uKHBhcmFtKXtcbiAgICB2YXIga2V5ID0gcGFyYW0ubmFtZTtcbiAgICByZXR1cm4gZW5jb2RlVVJJQ29tcG9uZW50KGtleSkgKyAnPScgKyBlbmNvZGVVUklDb21wb25lbnQoZGF0YVtrZXldKTtcbiAgfSkuam9pbignJicpO1xuXG4gIGlmKHF1ZXJ5UGFyYW1zKSB1cmwgKz0gJz8nICsgcXVlcnlQYXJhbXM7XG5cbiAgcmV0dXJuIHVybDtcbn07XG5cbmZ1bmN0aW9uIGFwcGx5UGF0aFBhcmFtcyh1cmwsIG9wZXJhdGlvbiwgZGF0YSl7XG4gIHZhciBwYXRoUGFyYW1zID0gb3BlcmF0aW9uLnBhcmFtZXRlcnMuZmlsdGVyKGZ1bmN0aW9uKHBhcmFtKXtcbiAgICByZXR1cm4gcGFyYW0ucGFyYW1UeXBlID09PSAncGF0aCc7XG4gIH0pO1xuXG4gIHZhciBtaXNzaW5nUGFyYW1zID0gcGF0aFBhcmFtcy5maWx0ZXIoZnVuY3Rpb24ocGFyYW0pe1xuICAgIHJldHVybiBkYXRhW3BhcmFtLm5hbWVdID09PSB1bmRlZmluZWQ7XG4gIH0pO1xuXG4gIGlmKG1pc3NpbmdQYXJhbXMubGVuZ3RoKXtcbiAgICB0aHJvdyBuZXcgTWlzc2luZ1BhdGhQYXJhbXNFcnJvcihtaXNzaW5nUGFyYW1zLm1hcChmdW5jdGlvbihwYXJhbSl7XG4gICAgICByZXR1cm4gcGFyYW0ubmFtZTtcbiAgICB9KSk7XG4gIH1cblxuICBwYXRoUGFyYW1zLmZvckVhY2goZnVuY3Rpb24ocGFyYW0pe1xuICAgIHZhciBrZXkgPSBwYXJhbS5uYW1lO1xuICAgIFxuICAgIHZhciBleHAgPSBuZXcgUmVnRXhwKCd7JyArIGtleSArICdbXn1dKn0nLCAnZ2knKTtcblxuICAgIHZhciB2YWx1ZSA9IGRhdGFba2V5XS50b1N0cmluZygpO1xuICAgIGRlbGV0ZSBkYXRhW2tleV07XG4gICAgdmFsdWUgPSB2YWx1ZS5zcGxpdCgnLycpLm1hcChlbmNvZGVVUklDb21wb25lbnQpLmpvaW4oJy8nKTtcblxuICAgIHVybCA9IHVybC5yZXBsYWNlKGV4cCwgdmFsdWUpO1xuICB9KTtcblxuICByZXR1cm4gdXJsO1xufVxuXG5mdW5jdGlvbiBnZXRVcmxUZW1wbGF0ZShvcGVyYXRpb24pe1xuICB2YXIgYXBpT2JqZWN0ID0gb3BlcmF0aW9uLmFwaU9iamVjdDsgXG5cbiAgdmFyIGJhc2VQYXRoID0gYXBpT2JqZWN0LmFwaURlY2xhcmF0aW9uLmJhc2VQYXRoO1xuICB2YXIgcGF0aCA9IGFwaU9iamVjdC5wYXRoLnJlcGxhY2UoJ3tmb3JtYXR9JywgJ2pzb24nKTtcbiAgXG4gIHJldHVybiBiYXNlUGF0aCArIHBhdGg7XG59XG4iLCIndXNlIHN0cmljdCc7XG5cbi8vIFByb21pc2UgcG9seWZpbGxcbnZhciBQcm9taXNlID0gcmVxdWlyZSgnZXM2LXByb21pc2UnKS5Qcm9taXNlO1xudmFyIGNsaWVudEdlbmVyYXRvciA9IHJlcXVpcmUoJ3N3YWdnZXItY2xpZW50LWdlbmVyYXRvcicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uKHNjaGVtYSl7XG4gIHJldHVybiBjbGllbnRHZW5lcmF0b3Ioc2NoZW1hLCByZXF1ZXN0SGFuZGxlcik7XG59O1xuXG4vLyBGb3IgbW9ja2luZyBkdXJpbmcgdW5pdCB0ZXN0aW5nXG5pZih0eXBlb2YgWE1MSHR0cFJlcXVlc3QgIT09ICd1bmRlZmluZWQnKXtcbiAgbW9kdWxlLmV4cG9ydHMuWE1MSHR0cFJlcXVlc3QgPSB3aW5kb3cuWE1MSHR0cFJlcXVlc3Q7XG59XG5cbmZ1bmN0aW9uIHJlcXVlc3RIYW5kbGVyKGVycm9yLCByZXF1ZXN0KXtcbiAgdmFyIFhNTEh0dHBSZXF1ZXN0ID0gbW9kdWxlLmV4cG9ydHMuWE1MSHR0cFJlcXVlc3Q7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbihyZXNvbHZlLCByZWplY3Qpe1xuICAgIGlmKGVycm9yKSByZXR1cm4gcmVqZWN0KGVycm9yKTtcblxuICAgIHZhciBtZXRob2QgPSByZXF1ZXN0Lm1ldGhvZDtcbiAgICB2YXIgdXJsID0gcmVxdWVzdC51cmw7XG4gICAgdmFyIGJvZHkgPSByZXF1ZXN0LmJvZHk7XG4gICAgdmFyIGhlYWRlcnMgPSByZXF1ZXN0LmhlYWRlcnM7XG5cbiAgICB2YXIgb3B0aW9ucyA9IHJlcXVlc3Qub3B0aW9ucztcbiAgICB2YXIgYXN5bmMgPSAoJ2FzeW5jJyBpbiBvcHRpb25zKT8gb3B0aW9ucy5hc3luYyA6IHRydWU7XG4gICAgdmFyIHhociA9IG5ldyBYTUxIdHRwUmVxdWVzdCgpO1xuXG4gICAgeGhyLm9wZW4obWV0aG9kLCB1cmwsIGFzeW5jKTtcblxuICAgIGlmKGhlYWRlcnMpe1xuICAgICAgT2JqZWN0LmtleXMoaGVhZGVycykuZm9yRWFjaChmdW5jdGlvbihoZWFkZXIpe1xuICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihoZWFkZXIsIGhlYWRlcnNbaGVhZGVyXSk7XG4gICAgICB9KTtcbiAgICB9XG4gICAgXG4gICAgaWYob3B0aW9ucy53aXRoQ3JlZGVudGlhbHMpIHhoci53aXRoQ3JlZGVudGlhbHMgPSBvcHRpb25zLndpdGhDcmVkZW50aWFscztcbiAgICBpZihvcHRpb25zLnRpbWVvdXQpIHhoci50aW1lb3V0ID0gb3B0aW9ucy50aW1lb3V0O1xuICAgIGlmKG9wdGlvbnMub25hYm9ydCkgeGhyLm9uYWJvcnQgPSBvcHRpb25zLm9uYWJvcnQ7XG4gICAgaWYob3B0aW9ucy5vbmVycm9yKSB4aHIub25lcnJvciA9IG9wdGlvbnMub25lcnJvcjtcbiAgICBpZihvcHRpb25zLm9ubG9hZCkgeGhyLm9ubG9hZCA9IG9wdGlvbnMub25sb2FkO1xuICAgIGlmKG9wdGlvbnMub250aW1lb3V0KSB4aHIub250aW1lb3V0ID0gb3B0aW9ucy5vbnRpbWVvdXQ7XG4gICAgaWYob3B0aW9ucy5vbnByb2dyZXNzKSB4aHIub25wcm9ncmVzcyA9IG9wdGlvbnMub25wcm9ncmVzcztcblxuICAgIHhoci5vbmxvYWRlbmQgPSBmdW5jdGlvbigpe1xuICAgICAgdmFyIGRhdGEgPSB0aGlzLnJlc3BvbnNlO1xuICAgICAgdmFyIGNvbnRlbnRUeXBlID0gdGhpcy5nZXRSZXNwb25zZUhlYWRlcignQ29udGVudC1UeXBlJyk7XG5cbiAgICAgIGlmKGNvbnRlbnRUeXBlICYmIGNvbnRlbnRUeXBlLmluZGV4T2YoJ2FwcGxpY2F0aW9uL2pzb24nKSAhPT0gLTEpe1xuICAgICAgICB0cnkge1xuICAgICAgICAgIGRhdGEgPSBKU09OLnBhcnNlKGRhdGEpO1xuICAgICAgICB9IGNhdGNoKGVycm9yKXtcbiAgICAgICAgICByZWplY3QoeyBcbiAgICAgICAgICAgIGVycm9yOiBlcnJvcixcbiAgICAgICAgICAgIHN0YXR1czogdGhpcy5zdGF0dXMsXG4gICAgICAgICAgICBkYXRhOiBkYXRhXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgaWYodGhpcy5zdGF0dXMgPCAyMDAgfHwgdGhpcy5zdGF0dXMgPj0gMzAwKXtcbiAgICAgICAgcmVqZWN0KHtcbiAgICAgICAgICBlcnJvcjogZXJyb3IsXG4gICAgICAgICAgc3RhdHVzOiB0aGlzLnN0YXR1cyxcbiAgICAgICAgICBkYXRhOiBkYXRhXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmVzb2x2ZShkYXRhKTtcbiAgICAgIH1cbiAgICAgIFxuICAgICAgaWYob3B0aW9ucy5vbmxvYWRlbmQpIG9wdGlvbnMub25sb2FkZW5kLmNhbGwodGhpcyk7XG4gICAgfTtcblxuICAgIHhoci5zZW5kKGJvZHkpO1xuICB9KTtcbn1cbiJdfQ== (27) });